实用指南:告别IP被封!分布式爬虫的“隐身”与“分身”术

news/2025/9/22 17:11:19/文章来源:https://www.cnblogs.com/ljbguanli/p/19105620

实用指南:告别IP被封!分布式爬虫的“隐身”与“分身”术

咱们平时上网爬材料,最头疼的就是IP被封。单台机器猛刷,网站一眼就能识破。想把活儿干得又快又稳,就得把任务拆开,让多台机器或多个进程一起干,每个还用不同的IP出口——这就好比让一群人轮流换装去排队,既减轻压力又降低风险。

在这里插入图片描述

下面是一个基于Python的分布式爬虫实现,启用多进程和代理隧道技术来分散请求压力并降低IP被封风险。

import multiprocessing
import requests
from urllib.parse import urlparse
import time
import random
from queue import Queue
import logging
from datetime import datetime
# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
class DistributedCrawler
:
def __init__(self, proxy_list, num_processes=4, requests_per_ip=100, delay_range=(1, 3)):
"""
初始化分布式爬虫
Args:
proxy_list: 代理服务器列表,格式为 [{"http": "http://ip:port", "https": "https://ip:port"}, ...]
num_processes: 进程数量
requests_per_ip: 每个IP发出的请求数量限制
delay_range: 请求延迟范围(秒)
"""
self.proxy_list = proxy_list
self.num_processes = num_processes
self.requests_per_ip = requests_per_ip
self.delay_range = delay_range
self.task_queue = multiprocessing.Queue()
self.result_queue = multiprocessing.Queue()
self.proxy_usage = multiprocessing.Manager().dict()
# 初始化代理使用计数
for proxy in proxy_list:
key = self._get_proxy_key(proxy)
self.proxy_usage[key] = 0
def _get_proxy_key(self, proxy):
"""生成代理的唯一标识"""
http_proxy = proxy.get('http', '')
https_proxy = proxy.get('https', '')
return f"{http_proxy
}_{https_proxy
}"
def add_tasks(self, urls):
"""添加任务到队列"""
for url in urls:
self.task_queue.put(url)
# 添加结束信号
for _ in range(self.num_processes):
self.task_queue.put(None)
def get_available_proxy(self):
"""获取可用的代理,基于使用次数进行负载均衡"""
# 按使用次数排序,选择使用最少的代理
sorted_proxies = sorted(
self.proxy_list,
key=lambda p: self.proxy_usage[self._get_proxy_key(p)]
)
# 返回使用次数未超限的代理
for proxy in sorted_proxies:
key = self._get_proxy_key(proxy)
if self.proxy_usage[key] < self.requests_per_ip:
self.proxy_usage[key] += 1
return proxy
# 如果所有代理都超限,随机选择一个并重置计数
proxy = random.choice(self.proxy_list)
key = self._get_proxy_key(proxy)
self.proxy_usage[key] = 1
return proxy
def worker(self, worker_id):
"""工作进程函数"""
logger.info(f"Worker {worker_id
} started")
while True:
url = self.task_queue.get()
if url is None: # 结束信号
break
try:
# 获取代理
proxy = self.get_available_proxy()
logger.info(f"Worker {worker_id
} using proxy: {proxy
}")
# 添加随机延迟
delay = random.uniform(*self.delay_range)
time.sleep(delay)
# 发送请求
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
response = requests.get(
url,
proxies=proxy,
headers=headers,
timeout=30
)
# 处理响应
if response.status_code == 200:
result = {
'url': url,
'content': response.text[:1000], # 只取前1000个字符
'status': 'success',
'worker_id': worker_id,
'proxy': proxy
}
self.result_queue.put(result)
logger.info(f"Worker {worker_id
} successfully crawled {url
}")
else:
self.result_queue.put({
'url': url,
'status': f'error: status code {response.status_code
}',
'worker_id': worker_id,
'proxy': proxy
})
logger.warning(f"Worker {worker_id
} got status code {response.status_code
} for {url
}")
except Exception as e:
self.result_queue.put({
'url': url,
'status': f'error: {
str(e)
}',
'worker_id': worker_id,
'proxy': proxy
})
logger.error(f"Worker {worker_id
} error crawling {url
}: {
str(e)
}")
logger.info(f"Worker {worker_id
} finished")
def run(self):
"""启动爬虫"""
processes = []
# 启动工作进程
for i in range(self.num_processes):
p = multiprocessing.Process(target=self.worker, args=(i,))
p.start()
processes.append(p)
# 等待所有进程完成
for p in processes:
p.join()
# 收集结果
results = []
while not self.result_queue.empty():
results.append(self.result_queue.get())
return results
# 示例使用
if __name__ == "__main__":
# 代理列表示例 (实际使用时需要替换为真实的代理IP)
proxy_list = [
{
"http": "http://proxy1.example.com:8080", "https": "https://proxy1.example.com:8080"
},
{
"http": "http://proxy2.example.com:8080", "https": "https://proxy2.example.com:8080"
},
{
"http": "http://proxy3.example.com:8080", "https": "https://proxy3.example.com:8080"
},
{
"http": "http://proxy4.example.com:8080", "https": "https://proxy4.example.com:8080"
},
]
# 要爬取的URL列表
urls_to_crawl = [
"https://httpbin.org/ip",
"https://httpbin.org/user-agent",
"https://httpbin.org/headers",
"https://httpbin.org/get",
] * 5 # 重复几次以展示分布式效果
# 创建分布式爬虫实例
crawler = DistributedCrawler(
proxy_list=proxy_list,
num_processes=4, # 使用4个进程
requests_per_ip=3, # 每个代理IP最多使用3次
delay_range=(1, 2) # 请求间隔1-2秒
)
# 添加任务
crawler.add_tasks(urls_to_crawl)
# 运行爬虫并获取结果
results = crawler.run()
# 打印结果摘要
success_count = sum(1 for r in results if r['status'] == 'success')
print(f"爬取完成! 成功: {success_count
}, 失败: {
len(results) - success_count
}")
# 打印部分结果
for i, result in enumerate(results[:3]):
print(f"结果 {i+1
}:")
print(f" URL: {result['url']
}")
print(f" 状态: {result['status']
}")
print(f" 工作进程: {result.get('worker_id', 'N/A')
}")
print(f" 使用的代理: {result.get('proxy', 'N/A')
}")
if 'content' in result:
print(f" 内容预览: {result['content'][:100]
}...")
print()

架构说明

这个分布式爬虫架构具备以下关键组件:

1、多进程工作模式:使用Python的multiprocessing模块创建多个工作进程,每个进程独立处理爬取任务。

2、代理隧道管理

  • 维护一个代理IP池
  • 实现负载均衡算法,优先选择利用次数较少的代理
  • 限制单个代理IP的请求频率,避免过度使用

3、任务队列:应用多进程安全的Queue来分配任务给各个工作进程。

4、随机化请求模式

  • 在每个请求之间添加随机延迟
  • 使用不同的User-Agent头部
  • 依据多个出口IP分散请求

扩展建议

对于更复杂的分布式爬虫系统,可以考虑以下扩展:

  1. 分布式任务队列:采用Redis或RabbitMQ替代multiprocessing.Queue,实现真正的跨机器分布式部署。

  2. 代理IP池服务:搭建独立的代理IP池服务,动态管理代理IP的可用性、速度和地域分布。

  3. 速率限制:建立更精细的请求速率控制,根据目标网站的robots.txt和实际响应调整请求频率。

  4. 故障恢复:添加重试机制和故障转移功能,提高环境的鲁棒性。

  5. 监控和日志:集成更完善的监控系统,实时跟踪爬虫状态、性能指标和错误率。

注意:在实际启用时,请确保遵守目标网站的robots.txt协议和相关法律法规,尊重网站的爬虫政策。

总之,分布式爬虫靠分工协作和IP轮换,把单个压力化解于无形。这样不仅效率翻倍,被封的风险也大大降低,让信息获取更加稳健顺畅。用好这个架构,爬虫就能像真正的团队作业一样,既高效又隐蔽。

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

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

相关文章

从 “盲调” 到 “精准优化”:SQL Server 表统计信息实战指南

本文核心要旨在于:SQL Server 表统计信息作为元数据对象,宛如数据分布的 "指南针",精准存储着数据分布信息,为查询优化器提供关键依据,助力其生成高效的查询执行计划。在维护方面,统计信息更新有手动与…

别的摄像机都能国标GB28181注册上,就这台海康摄像机注册不上来,国标配置都反复检查没问题

别的摄像机都能国标GB28181注册上,就这台海康摄像机注册不上来,国标配置都反复检查没问题先看看下午EasyGBS群里用户提到的问题,我先大概描述一下,用户说有一台海康的摄像机IPC国标注册不到EasyGBS,另一台可以,区…

保护眼睛小程序

import wx import time from datetime import datetime, timedelta class MyFrame(wx.Frame): def init(self): super().init(None, title=用眼提醒, size=wx.Size(800, 600)) self.SetWindowStyle(wx.STAY_ON_TOP)# 创…

公司有网站域名 如何做网站传媒公司做网站编辑 如何

同一个浏览器登录不同账号session一致&#xff0c;这就导致后面登录的用户数据会把前面登录的用户数据覆盖掉&#xff0c;这个问题很常见&#xff0c;当前我这边解决的就是同一个浏览器不同窗口只能登录一个用户&#xff0c;解决方案如下&#xff1a; 1、在App.vue中监听本地数…

石家庄网站外包有多少种做网站后台程序

Java 集合交集判断 一. 使用 retainAll()方法二. 使用 removeAll() 方法与判断集合大小三. 使用 Stream 流式处理四. 使用 Collections.disjoint() 方法五. 总结六. 参考文章 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续…

视频网站做板块栏目手机大全网站

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-12-31&#xff09;山西电力市场全天平均日前电价为445.23元/MWh。其中&#xff0c;最高日前电价为791.27元/MWh&#xff0c;预计出现在08:15。最低日前电价为270.52元/MWh&#xff0c;预计…

做的网站上传到服务器专业制作效果图公司

今天给大家分享的题目是leetcode242有效的字母异位词 我们先看题目描述&#xff1a; Chatgpt中对于字母异位词的解释如下&#xff1a; 字母异位词是指由相同的字母组成但顺序不同的单词。换句话说&#xff0c;字母异位词具有相同的字母&#xff0c;只是排列顺序不同。 简单的将…

备案可以不关闭网站吗科技设计网站建设

排序思想掌握 前言&#xff1a; 开发当中为什么会用到算法&#xff1f;或者说为什么需要算法与数据结构等&#xff1f; 算法思想可以帮助我们优化程序的性能&#xff0c;例如减少时间与空间复杂度&#xff0c;从而使程序更快、更有效地运行。在数据分析领域&#xff0c;算法思想…

做模具做什么网站做外贸的人经常用什么网站

Zookeeper 架构理解 整体架构 Follower server 可以直接处理读请求&#xff0c;但不能直接处理写请求。写请求只能转发给 leader server 进行处理。最终所有的写请求在 leader server 端串行执行。&#xff08;因为分布式环境下永远无法精确地确认不同服务器不同事件发生的先后…

做网站维护有危险吗官网制作需要多少钱

uniapp嵌套webview&#xff0c;如何解决回退问题&#xff1f; 文章目录 uniapp嵌套webview&#xff0c;如何解决回退问题&#xff1f;遇到问题解决方式方式一方式二 场景&#xff1a; 进入首页&#xff0c;自动跳转第三方应用 遇到问题 在设备上运行时&#xff0c;无法回退上…

杭州滨江的网站建设公司众筹 wordpress

每次刚装完系统我们访问GitHub就会出现无法访问的情况&#xff0c;此时只需要修改host文件将可访问的dns解析地址写入进去即可。 查询DNS 使用dns监测查询工具 https://tool.chinaz.com/dns https://dnsdaquan.com/ 输入无法访问的IP github.com 进行检测 查询到可访问的i…

如何创建外卖网站优秀广告设计案例作品欣赏

压缩包的内容 里面有secret.txt文件&#xff0c;用ARCHPR工具套上字典&#xff0c;爆破压缩包密码。密码为pavilion 解压得到原图&#xff0c;并且有了加密后的图片&#xff0c;根据代码里的key和参数直接运行脚本解密水印图片&#xff1a; import cv2 import numpy as np imp…

贵州专业网站建设公司如果做公司网站

写在前面&#xff1a; 博主本人大学期间参加数学建模竞赛十多余次&#xff0c;获奖等级均在二等奖以上。为了让更多学生在数学建模这条路上少走弯路&#xff0c;故将数学建模常用数学模型算法汇聚于此专栏&#xff0c;希望能够对要参加数学建模比赛的同学们有所帮助。 目录 1. …

[::-1]的用法

[::-1] 是 Python 中一种非常简洁且常用的切片(slice)语法,它的作用是反转序列。 它可以用在多种数据类型上,包括:列表 (list) 字符串 (string) 元组 (tuple) NumPy 数组语法解析 切片语法的一般形式是:[start:s…

003_for循环操作列表和元组

1、for循环遍历整个列表 cars = ["奔驰", "比亚迪", "长安", "理想"] cars.insert(0, "红旗") cars.append("长安") cars.insert(len(cars), "宝马…

linux 文件传输命令

在 Linux 系统中,有多种命令可用于文件传输,适用于不同场景(本地传输、网络传输、不同协议等)。以下是常用的文件传输命令: 1. 本地文件传输命令 cp - 复制文件 / 目录 最基础的本地文件复制命令bash# 复制文件 c…

济南网站备案编写软件开发文档

2024年淘宝天猫618活动&#xff0c;将于2024年5月19日开始&#xff0c;今年618淘宝天猫取消了预售环节。同时&#xff0c;618淘宝天猫也提供了多项优惠活动&#xff1a;超级红包、跨店满减、官方立减、全程价保及草柴APP领优惠券拿购物返利等多重优惠活动。 2024年淘宝天猫618…

黑龙江省城乡建设厅网站首页高端app开发

1.进程间通信概述 UNIX系统IPC是各种进程通信方式的统称。 2.管道通信原理 特点&#xff1a; 1.它是半双工的&#xff08;即数据只能在一个方向上流动&#xff09;&#xff0c;具有固定的读端和写端。 2.它只能用于具有亲缘关系的进程之间通信&#xff08;也是父子进程或者…

济南网站开发公司价格比较网

Ragas是一个框架&#xff0c;它可以帮助你从不同的方面评估你的问答&#xff08;QA&#xff09;流程。它为你提供了一些指标来评估你的问答系统的不同方面&#xff0c;具体包括&#xff1a; 评估检索&#xff08;context&#xff09;的指标&#xff1a;提供了上下文相关性&…