Python构建免费爬虫代理池实战:从抓取到验证
本文详解如何使用Python构建一个轻量级的爬虫代理池。通过抓取西祠胡同等免费代理网站,利用PyQuery解析数据并存入List,实现HTTP与HTTPS代理的分类管理。文章提供了代理有效性检测、随机调用及失效清理的核心代码逻辑,并探讨了基于分数的代理维护机制,帮助开发者应对403限制。
在进行网络数据爬取时,频繁遭遇403状态码是常见现象,这通常意味着目标网站对当前IP实施了访问频率限制。应对此类反爬机制的有效策略是使用代理IP,当主IP被封禁时,可切换至其他可用IP。大型机构通常采购稳定的付费代理服务,而个人开发者或资源有限的用户则多依赖网上提供的免费代理资源。
常见的做法是从互联网抓取一批免费代理IP,并将其持久化存储于Excel文件或数据库(如MySQL、Redis)中,通过定期维护确保代理的可用性。然而,这种方案存在环境依赖问题:若运行爬虫的机器未安装Excel或特定的数据库软件,代理池将无法正常运行。
鉴于作者此前从事Java开发,习惯将常用数据存入ArrayList以保证高效便捷,因此借鉴该经验,在Python中采用List列表来存储爬取的代理IP,构建一个内存中的代理池,并对其进行持续维护。
文中选取西祠胡同(xicidaili)和swei360等免费代理网站作为数据源,这些资源足以满足大多数常规爬虫需求。实现过程中需依赖requests和pyquery库,若未安装请自行补充。
首先介绍如何从西祠胡同网站抓取代理数据。需定义一个抓取方法,接收两个参数:目标URL和需要爬取的页数。具体实现代码如下:
def get_xicidaili_proxy(url,page):
for i in range(1,page):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
response = requests.get(url + str(i), headers=headers)
html = response.text
doc = pq(html)
ip_list = doc('#ip_list')('tr:gt(0)').items()
for item in ip_list:
ip = item.find('td:nth-child(2)').text()
port = item.find('td:nth-child(3)').text()
http_type = item.find('td:nth-child(6)').text()
proxy_ip = http_type + "://" + ip + ":" + port
if http_type == 'HTTP':
http_proxy_pool.append(proxy_ip)
elif http_type == 'HTTPS':
https_proxy_pool.append(proxy_ip)
# print(proxy_ip)
代码中定义了http_proxy_pool和https_proxy_pool两个列表,分别用于存储HTTP和HTTPS类型的代理。利用PyQuery通过CSS选择器提取IP、端口及协议类型,并将其组合为“协议://IP:端口”格式的字符串,存入对应的代理列表中。
抓取swei360网站代理的原理与上述过程一致,此处不再赘述具体代码。
在使用代理前,必须验证其有效性。通过发送GET请求并检查返回状态码来判断:若返回200,则代理可用;其他状态码则视为不可用。相关验证代码如下:
def detect_proxy(test_url,http_type,proxy):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
proxy={
http_type : proxy
}
try:
response = requests.get(test_url,proxies=proxy,headers=headers)
if response.status_code in [200]:
print('代理可用',proxy)
return True
else:
print('代理不可用', proxy);
delete_proxy(http_type,proxy)
return False
except(requests.exceptions.ProxyError,RequestException):
print('代理不可用', proxy)
delete_proxy(http_type, proxy)
return False
定义detect_proxy方法用于检测代理状态,参数包括测试网址、代理类型(HTTP/HTTPS)及代理IP地址。若requests请求返回状态码200,则判定代理可用并返回True;否则返回False。若遇到requests异常或其他错误,同样视为不可用并返回False。对于检测为不可用的代理,需从代理池中移除。
从代理池获取代理时,采用随机抽取策略,以避免频繁使用同一IP导致被目标网站拒绝访问。具体实现代码如下:
def get_https_proxy(): proxy_ip = random.choice(https_proxy_pool) return proxy_ip def get_http_proxy(): proxy_ip = random.choice(http_proxy_pool) return proxy_ip
为确保代理池的纯净度,一旦检测到代理不可用,应及时从http_proxy_pool或https_proxy_pool列表中将其删除。
至此,一个简单的爬虫代理池已搭建完成,核心流程总结如下:
- 从免费代理网站抓取代理信息,并将其存储在List列表中。
- 提供从代理池中随机获取代理的功能。鉴于HTTP和HTTPS网站对代理类型有特定要求,分别提供了获取HTTP和HTTPS类型代理的独立方法。
- 提供检测代理有效性的方法,若代理可用返回True,不可用则返回False。
- 提供删除失效代理的方法,以清理代理池。
当前实现的代理池较为简单,存在一个潜在缺陷:仅以状态码是否为200作为判断标准。若返回其他代码,可能由网络波动或测试网站不可访问引起,并不一定代表代理本身失效。更优的做法是为每个代理设置初始分值(如10分),检测不可用时扣分,分数归零时彻底移除;检测可用时重置为满分。
这种基于分数的机制为失效代理提供了“改过自新”的机会,避免了因单次网络波动而直接将其剔除的“一刀切”做法。
以上即为本文关于Python爬虫代理池搭建的全部内容,希望对读者有所帮助,欢迎支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









