因为需要进行一个大规模的爬取,具体是爬取全国地级以上城市的实时天气,历史某天到某天的天气,未来30天的天气,为了防止IP被封,需要使用代理IP进行爬取,而找了半天也没有找到好用的可以获取代理IP的库,所以就自己写了一个。流程大概是从免费代理IP 网站爬取IP,加入到IP池,并维护这个IP 池,在使用别的爬虫时,导入这个库,就可以使用代理IP爬取,适用于大规模爬虫。
可以定位到 我们需要的IP地址和端口号在class=“clearfix proxies” 的 tr 标签中
# -*- 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 = urllib.request.build_opener() opener.addheaders = [headers] # 将opener安装为全局 urllib.request.install_opener(opener)
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
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')
代码下载地址:
点我