爬虫代理IP池
爬虫代理IP池实现
1. 代码目标
因为需要进行一个大规模的爬取,具体是爬取全国地级以上城市的实时天气,历史某天到某天的天气,未来30天的天气,为了防止IP被封,需要使用代理IP进行爬取,而找了半天也没有找到好用的可以获取代理IP的库,所以就自己写了一个。流程大概是从免费代理IP 网站爬取IP,加入到IP池,并维护这个IP 池,在使用别的爬虫时,导入这个库,就可以使用代理IP爬取,适用于大规模爬虫。
2. 选取一个免费代理IP的网站
3. F12查看网页结构
可以定位到 我们需要的IP地址和端口号在class=“clearfix proxies” 的 tr 标签中
4. 编写代码
导入库
# -*- coding: utf-8 -*-
import os
import time
import urllib.request
from bs4 import BeautifulSoup as BS
import requests
请求头
headers = ("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 "
"Safari/537.36")
opener对象
opener = urllib.request.build_opener()
opener.addheaders = [headers]
# 将opener安装为全局
urllib.request.install_opener(opener)
构建url并调用解析函数进行解析
url = "http://www.xicidaili.com/nn/1"
htmlsrc = urllib.request.urlopen(url).read().decode("utf-8")
bs = BS(htmlsrc, "html.parser")
ipInfo = ipParser(bs)
写入到文件
fn = filepath_filename+'.txt' # IP池文件
f = open(fn, 'a')
for ip in ipInfo:
f.write(ip)
f.write('\n')
页面解析
htmlBody = bs.find('div', class_='clearfix proxies')
ip_list_1 = htmlBody.find_all('tr')
for i in range(1, len(ip_list_1)-1):
container.append(ip_list_1[i].contents[3].text + ':' + ip_list_1[i].contents[5].text + ' '+str(0))
return container
5. 使用此库
导入
import scrapyIP as vIp
使用
vIp.scrapyIp(ipList_filepath_filename)
global overall_ip_list
overall_ip_list = vIp.readIp(ipList_filepath_filename + '.txt')
这样得到的ip表就是 overall_ip_list
需要注意的是,为了便于维护,我在每个ip后面增加了一个变量,用来表的可访问度
如下:
115.151.7.167:9999 0
110.52.235.6:9999 0
110.52.235.3:9999 0
初始化为0,在使用爬虫时,如果使用此代理IP访问目标网站失败,可访问度减1,成功就加1。
index = random.randint(0, len(overall_ip_list) - 1)
bsStr = overall_ip_list[index][0]
try:
requests.get('网站url', proxies={"http": "http://%s" % (bsStr)}, timeout=30)
except:
print('connect failed') # 不能访问,继续选取
# 对可访问做一个量化,越大表示越可访问,不可访问减1
visit_degree = overall_ip_list[index][1]
int_visit_degree = int(visit_degree)
int_visit_degree = int_visit_degree - 1
overall_ip_list[index][1] = int_visit_degree
return randomGetIP(city)
else:
print('success')
visit_degree = overall_ip_list[index][1]
int_visit_degree = int(visit_degree)
int_visit_degree = int_visit_degree + 1
overall_ip_list[index][1] = int_visit_degree
print(bsStr)
px = urllib.request.ProxyHandler({'http': '%s' % (bsStr)})
return px
每隔一段时间,对小于一定值的IP进行清理
# 剔除目前ip表中可靠性低的ip
i = 0
global overall_ip_list
while i < len(overall_ip_list):
if int(overall_ip_list[i][1]) < -5: # 可靠性低于-5
overall_ip_list.pop(i)
i -= 1
i += 1
# 将目前的ip表写入到文件,覆盖之前的
fr = open(iplist_filepath_filename + '.txt', 'w')
for ip0 in overall_ip_list:
fr.write(str(ip0[0]) + ' ' + str(ip0[1]))
fr.write('\n')
fr.close()
# 爬取ip并追加写入到文件
vIp.scrapyIp(iplist_filepath_filename)
# 读取文件为IP表
overall_ip_list = vIp.readIp(iplist_filepath_filename + '.txt')
代码下载地址:
点我