Go语言多线程爬虫与代理IP反爬

news2025/5/13 13:07:38

有个朋友想用Go语言编写一个多线程爬虫,并且使用代理IP来应对反爬措施。多线程在Go中通常是通过goroutine实现的,所以应该使用goroutine来并发处理多个网页的抓取。然后,代理IP的话,可能需要一个代理池,从中随机选择代理来发送请求,避免同一个IP被封锁。大体思路就是这样,具体看我下面实操吧。

在这里插入图片描述

以下是一个使用Go语言编写的多线程爬虫程序,结合代理IP和反爬策略的示例代码:

package main

import (
	"bufio"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"net/url"
	"os"
	"sync"
	"time"
)

var (
	proxyPool  []*url.URL
	proxyMux   sync.Mutex
	userAgents = []string{
		"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
		"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
		"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
	}
	visitedURLs sync.Map
)

func main() {
	// 初始化随机种子
	rand.Seed(time.Now().UnixNano())

	// 加载代理列表
	if err := loadProxies("proxies.txt"); err != nil {
		fmt.Println("Error loading proxies:", err)
		return
	}

	// 创建任务通道
	taskChan := make(chan string, 100)
	
	// 启动worker
	var wg sync.WaitGroup
	workerCount := 10
	for i := 0; i < workerCount; i++ {
		wg.Add(1)
		go worker(taskChan, &wg)
	}

	// 添加初始任务
	go func() {
		taskChan <- "https://httpbin.org/ip"
		taskChan <- "https://example.com"
	}()

	// 等待所有worker完成(实际可能需要其他停止机制)
	wg.Wait()
	close(taskChan)
}

func loadProxies(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		proxyURL, err := url.Parse("http://" + line)
		if err != nil {
			continue
		}
		proxyPool = append(proxyPool, proxyURL)
	}
	return nil
}

func worker(taskChan <-chan string, wg *sync.WaitGroup) {
	defer wg.Done()

	for targetURL := range taskChan {
		// URL去重
		if _, loaded := visitedURLs.LoadOrStore(targetURL, true); loaded {
			continue
		}

		// 随机延迟(1-3秒)
		time.Sleep(time.Duration(1+rand.Intn(2)) * time.Second)

		// 获取随机代理
		proxy := getRandomProxy()
		if proxy == nil {
			fmt.Println("No available proxies")
			continue
		}

		// 创建自定义Transport
		transport := &http.Transport{
			Proxy: http.ProxyURL(proxy),
			DialContext: (&net.Dialer{
				Timeout:   10 * time.Second,
				KeepAlive: 10 * time.Second,
			}).DialContext,
			TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
			MaxIdleConns:          100,
			IdleConnTimeout:       90 * time.Second,
			TLSHandshakeTimeout:   10 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
		}

		// 创建HTTP客户端
		client := &http.Client{
			Transport: transport,
			Timeout:   15 * time.Second,
		}

		// 创建请求
		req, err := http.NewRequest("GET", targetURL, nil)
		if err != nil {
			fmt.Printf("Error creating request: %v\n", err)
			continue
		}

		// 设置随机User-Agent
		req.Header.Set("User-Agent", userAgents[rand.Intn(len(userAgents))])

		// 发送请求
		resp, err := client.Do(req)
		if err != nil {
			fmt.Printf("Error fetching %s: %v\n", targetURL, err)
			markBadProxy(proxy)
			continue
		}
		defer resp.Body.Close()

		// 处理响应
		if resp.StatusCode != http.StatusOK {
			fmt.Printf("Non-200 status code: %d for %s\n", resp.StatusCode, targetURL)
			continue
		}

		// 读取响应内容
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Printf("Error reading response body: %v\n", err)
			continue
		}

		// 处理页面内容(示例:输出内容长度)
		fmt.Printf("Successfully fetched %s (%d bytes) using proxy %s\n",
			targetURL, len(body), proxy.Host)

		// 这里可以添加链接提取和任务添加逻辑
		// parseLinks(body, taskChan)
	}
}

func getRandomProxy() *url.URL {
	proxyMux.Lock()
	defer proxyMux.Unlock()

	if len(proxyPool) == 0 {
		return nil
	}
	return proxyPool[rand.Intn(len(proxyPool))]
}

func markBadProxy(badProxy *url.URL) {
	proxyMux.Lock()
	defer proxyMux.Unlock()

	for i, p := range proxyPool {
		if p.String() == badProxy.String() {
			// 移除无效代理
			proxyPool = append(proxyPool[:i], proxyPool[i+1:]...)
			fmt.Printf("Removed bad proxy: %s\n", badProxy.String())
			break
		}
	}
}

// 示例链接解析函数(需要根据实际情况实现)
func parseLinks(body []byte, taskChan chan<- string) {
	// 这里可以添加HTML解析逻辑,提取链接并发送到taskChan
	// 注意:需要处理相对路径转换和域名限制
}

关键特性说明:

  1. 代理管理

    • 从文件加载代理列表(格式:ip:port)
    • 随机选择代理进行请求
    • 自动移除失效代理
  2. 反爬策略

    • 随机User-Agent轮换
    • 请求间随机延迟(1-3秒)
    • 自动代理失效检测和移除
    • 支持HTTPS和跳过证书验证
  3. 并发控制

    • 使用带缓冲的channel作为任务队列
    • 可配置的worker数量
    • 自动URL去重(使用sync.Map)
  4. 健壮性设计

    • 连接超时设置(15秒)
    • 自定义Transport参数优化
    • 完善的错误处理

使用说明:

  1. 创建代理文件proxies.txt,格式为每行一个代理地址(ip:port)
  2. 根据需求调整以下参数:
    • workerCount:并发worker数量
    • taskChan缓冲大小
    • 各种超时参数
    • 随机延迟时间范围
  3. 实现parseLinks函数来提取新链接
  4. 添加具体的页面解析逻辑

注意事项:

  1. 代理质量直接影响爬虫效果,建议使用优质代理服务
  2. 根据目标网站的robots.txt和版权政策合理使用
  3. 添加适当的速率限制避免对目标网站造成过大压力
  4. 对于复杂反爬机制可能需要添加更多策略:
    • Cookie管理
    • JavaScript渲染支持
    • 验证码识别
    • 请求头随机化
    • 请求参数随机化

上面代码就是我提供了基础的爬虫框架,大家在使用的时候可以根据具体需求进行扩展和优化,有了这样的代码示例能让你们省很多事情。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2374677.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

node.js 实战——express图片保存到本地或服务器(七牛云、腾讯云、阿里云)

本地 ✅ 使用formidable 读取表单内容 npm i formidable ✅ 使用mime-types 获取图片后缀 npm install mime-types✅ js 中提交form表单 document.getElementById(uploadForm).addEventListener(submit, function(e){e.preventDefault();const blob preview._blob;if(!blob)…

Shadertoy着色器移植到Three.js经验总结

Shadertoy是一个流行的在线平台&#xff0c;用于创建和分享WebGL片段着色器。里面有很多令人惊叹的画面&#xff0c;甚至3D场景。本人也移植了几个ShaderToy上的着色器。本文将详细介绍移植过程中需要注意的关键点。 1. 基本结构差异 想要移植ShaderToy的shader到three.js&am…

电脑端音乐播放器推荐:提升你的听歌体验!

在快节奏的职场环境中&#xff0c;许多上班族都喜欢用音乐为工作时光增添色彩。今天要分享的这款音乐工具&#xff0c;或许能为你的办公时光带来意想不到的惊喜。 一、软件介绍-澎湃 澎湃音乐看似是个普通的播放器&#xff0c;实则藏着强大的资源整合能力。左侧功能栏清晰陈列着…

VIC-2D 7.0 为平面样件机械试验提供全视野位移及应变数据软件

The VIC-2D系统是一个完全集成的解决方案&#xff0c;它基于优化的相关算法为平面试样的力学测试提供非接触、全场的二维位移和应变数据&#xff0c;可测量关注区域内的每个像素子集的面内位移&#xff0c;并通过多种张量选项计算全场应变。The VIC-2D 系统可测量超过 2000%变形…

一周学完计算机网络之三:1、数据链路层概述

简单的概述 数据链路层是计算机网络体系结构中的第二层&#xff0c;它在物理层提供的基本服务基础上&#xff0c;负责将数据从一个节点可靠地传输到相邻节点。可以将其想象成一个负责在两个相邻的网络设备之间进行数据 “搬运” 和 “整理” 的 “快递中转站”。 几个重要概念…

单片机-STM32部分:13-1、蜂鸣器

飞书文档https://x509p6c8to.feishu.cn/wiki/V8rpwIlYIiEuXLkUljTcXWiKnSc 一、应用场景 大部分的电子产品、家电&#xff08;风扇、空调、电水壶&#xff09;都会有蜂鸣器&#xff0c;用于提示设备的工作状态 二、原理 蜂鸣器是一种将电信号转换为声音信号的器件&#xff0…

动态IP技术赋能业务创新:解锁企业数字化转型新维度

在数字经济高速发展的今天&#xff0c;IP地址已不再是简单的网络标识符&#xff0c;而是演变为支撑企业数字化转型的核心基础设施之一。动态IP技术凭借其灵活、高效、安全的特性&#xff0c;正在重塑传统业务模式&#xff0c;催生出诸多创新应用场景。本文将深入剖析动态IP的技…

TDengine 在金融领域的应用

简介 金融行业正处于数据处理能力革新的关键时期。随着市场数据量的爆炸式增长和复杂性的日益加深&#xff0c;金融机构面临着寻找能够高效处理大规模、高频次以及多样化时序数据的大数据处理系统的迫切需求。这一选择将成为金融机构提高数据处理效率、优化交易响应时间、提高…

OSCP - Hack The Box - Sau

主要知识点 CVE-2023-27163漏洞利用systemd提权 具体步骤 执行nmap扫描&#xff0c;可以先看一下55555端口 Nmap scan report for 10.10.11.224 Host is up (0.58s latency). Not shown: 65531 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp o…

QT6 源(93)篇三:阅读与注释共用体类 QVariant 及其源代码,本类支持比较运算符 ==、!=。

&#xff08;9&#xff09; 本类支持比较运算符 、! &#xff1a; 可见&#xff0c; QString 类型里可存储多个 unicode 字符&#xff0c;即使只存储一个 unicode 字符也不等于 QChar。 &#xff08;10&#xff09;本源代码来自于头文件 qvariant . h &#xff1a; #ifndef Q…

Maven私服搭建与登录全攻略

目录 1.背景2.简介3.安装4.启动总结参考文献 1.背景 回顾下maven的构建流程&#xff0c;如果没有私服&#xff0c;我们所需的所有jar包都需要通过maven的中央仓库或者第三方的maven仓库下载到本地&#xff0c;当一个公司或者一个团队所有人都重复的从maven仓库下载jar包&#…

力扣210(拓扑排序)

210. 课程表 II - 力扣&#xff08;LeetCode&#xff09; 这是一道拓扑排序的模板题。简单来说&#xff0c;给出一个有向图&#xff0c;把这个有向图转成线性的排序就叫拓扑排序。如果有向图中有环就没有办法进行拓扑排序了。因此&#xff0c;拓扑排序也是图论中判断有向无环图…

C++ asio网络编程(5)简单异步echo服务器

上一篇文章:C asio网络编程(4)异步读写操作及注意事项 文章目录 前言一、Session类1.代码2.代码详解3.实现Session类1.构造函数2.handle_read3.介绍一下boost的封装函数和api4.handle_write 二、Server类1.代码2.代码思路详解 三、客户端四、运行截图与流程图 前言 提示&…

【机器人】复现 UniGoal 具身导航 | 通用零样本目标导航 CVPR 2025

UniGoal的提出了一个通用的零样本目标导航框架&#xff0c;能够统一处理多种类型的导航任务。 支持 对象类别导航、实例图像目标导航和文本目标导航&#xff0c;而无需针对特定任务进行训练或微调。 本文分享UniGoal复现和模型推理的过程&#xff5e; 查找沙发&#xff0c;模…

spring中的@PropertySource注解详解

一、核心功能与作用 PropertySource是Spring框架中用于加载外部配置文件的核心注解&#xff0c;主要作用是将属性文件&#xff08;如.properties、.yml&#xff09;的键值对加载到Spring的Environment环境中&#xff0c;实现配置与代码的解耦。其核心价值包括&#xff1a; 外部…

二极管钳位电路——Multisim电路仿真

目录 二极管钳位电路 2.1 二极管正向钳位电路 二极管压降测试 2.1.1 二极管正向钳位电路图 2.1.2 二极管正向钳位工作原理 2.2 二极管负向钳位电路 2.2.1 二极管负向钳位电路图 2.2.2 二极管负向钳位工作原理 二极管正向反向钳位仿真电路实验结果 2.3 二极管顶部钳位…

suricata增加单元测试编译失败

一、环境 $ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 22.04.5 LTS Release: 22.04 Codename: jammysuricata: suricata7.0.5 IDE: vscode 二、背景 在suricata中开发了某个功能后&#xff0c;增加unittest时&#xff0c;…

高并发场景下的BI架构设计:衡石分布式查询引擎与缓存分级策略

在电商大促、金融交易时段或IoT实时监控场景中&#xff0c;企业BI系统常面临瞬时万级并发查询的冲击——运营团队需要实时追踪GMV波动&#xff0c;风控部门需秒级响应欺诈检测&#xff0c;产线监控需毫秒级反馈设备状态。传统单体架构的BI系统在此类场景下极易崩溃&#xff0c;…

鱼眼摄像头(一)多平面格式 单缓冲读取图像并显示

鱼眼摄像头&#xff08;一&#xff09;多平面格式 单缓冲读取图像并显示 1.摄像头格式 1. 单平面格式&#xff08;Single Plane&#xff09;&#xff1a;各通道数据保存在同一个平面&#xff08;缓冲&#xff09;&#xff0c;图像数据按行连续存储a. mjpeg&#xff0c;yuyv等…

机器学习笔记——特征工程

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本笔记介绍机器学习中常见的特征工程方法、正则化方法和简要介绍强化学习。 文章目录 特征工程&#xff08;Fzeature Engineering&#xff09;1. 特征提取&#xff…