Python搭建代理IP池实现获取IP的方法
使用爬虫时,大部分网站都有一定的反爬措施,有些网站会限制每个IP的访问速度或访问次数,超出了它的限制你的IP就会被封掉。对于访问速度的处理比较简单,只要间隔一段时间爬取一次就行了,避免频繁访问;而对于访问次数,就需要使用代理IP来帮忙了,使用多个代理IP轮换着去访问目标网址可以有效地解决问题。
目前网上有很多的代理服务网站提供代理服务,也提供一些免费的代理,但可用性较差,如果需求较高可以购买付费代理,可用性较好。
因此我们可以自己构建代理池,从各种代理服务网站中获取代理IP,并检测其可用性(使用一个稳定的网址来检测,最好是自己将要爬取的网站),再保存到数据库中,需要使用的时候再调用。
代码地址:https://github.com/Stevengz/Proxy_pool
另外三篇:
Python搭建代理IP池(二)-存储IP
Python搭建代理IP池(三)-检测IP
Python搭建代理IP池(四)-接口设置与整体调度
本文介绍的则是构建代理IP池的第一步:获取IP
使用的库:requests、pyquery
几个能提供免费代理的代理服务网站(排名不分先后):
| 厂商名称 | 地址 |
|---|---|
| 66代理 | http://www.66ip.cn/ |
| 西刺代理 | https://www.xicidaili.com |
| 全网代理 | http://www.goubanjia.com |
| 云代理 | http://www.ip3366.net |
| IP海 | http://www.iphai.com |
| 快代理 | https://www.kuaidaili.com |
| 免费代理IP库 | http://ip.jiangxianli.com |
代理服务网站Crawler
代理获取的相关代码,把从每个网站提取IP的方法都放到一起,然后运行时只要调用相关方法即可
为了实现灵活,将获取代理的一个个方法统一定义一个规范,如统一定义以crawl开头,这样扩展的时候只需要添加crawl开头的方法即可
在这里实现了几个示例,如抓取代理66、西刺代理、云代理、快代理四个免费代理网站,这些方法都定义成生成器,通过yield返回。首先将网页获取,然后用PyQuery解析,解析出IP加端口形式的代理再返回
crawler.py
importjson
importre
fromutilsimportget_page
frompyqueryimportPyQueryaspq
#元类
classProxyMetaclass(type):
def__new__(cls,name,bases,attrs):
count=0
attrs['__CrawlFunc__']=[]
fork,vinattrs.items():
if'crawl_'ink:
attrs['__CrawlFunc__'].append(k)
count+=1
attrs['__CrawlFuncCount__']=count
returntype.__new__(cls,name,bases,attrs)
classCrawler(object,metaclass=ProxyMetaclass):
defget_proxies(self,callback):
proxies=[]
forproxyineval("self.{}()".format(callback)):
print('成功获取到代理',proxy)
proxies.append(proxy)
returnproxies
defcrawl_daili66(self,page_count=4):
start_url='http://www.66ip.cn/{}.html'
urls=[start_url.format(page)forpageinrange(1,page_count+1)]
forurlinurls:
print('Crawling',url)
html=get_page(url)
ifhtml:
doc=pq(html)
trs=doc('.containerboxtabletr:gt(0)').items()
fortrintrs:
ip=tr.find('td:nth-child(1)').text()
port=tr.find('td:nth-child(2)').text()
yield':'.join([ip,port])
defcrawl_xicidaili(self):
foriinrange(1,3):
start_url='http://www.xicidaili.com/nn/{}'.format(i)
headers={
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Host':'www.xicidaili.com',
'Referer':'http://www.xicidaili.com/nn/3',
'Upgrade-Insecure-Requests':'1',
}
html=get_page(start_url,options=headers)
ifhtml:
find_trs=re.compile('(.*?)',re.S)
trs=find_trs.findall(html)
fortrintrs:
find_ip=re.compile('(\d+\.\d+\.\d+\.\d+) ')
re_ip_address=find_ip.findall(tr)
find_port=re.compile('(\d+) ')
re_port=find_port.findall(tr)
foraddress,portinzip(re_ip_address,re_port):
address_port=address+':'+port
yieldaddress_port.replace('','')
defcrawl_ip3366(self):
foriinrange(1,4):
start_url='http://www.ip3366.net/?stype=1&page={}'.format(i)
html=get_page(start_url)
ifhtml:
find_tr=re.compile('(.*?) ',re.S)
trs=find_tr.findall(html)
forsinrange(1,len(trs)):
find_ip=re.compile('(\d+\.\d+\.\d+\.\d+) ')
re_ip_address=find_ip.findall(trs[s])
find_port=re.compile('(\d+) ')
re_port=find_port.findall(trs[s])
foraddress,portinzip(re_ip_address,re_port):
address_port=address+':'+port
yieldaddress_port.replace('','')
defcrawl_kuaidaili(self):
foriinrange(1,4):
start_url='http://www.kuaidaili.com/free/inha/{}/'.format(i)
html=get_page(start_url)
ifhtml:
ip_address=re.compile('(.*?)')
re_ip_address=ip_address.findall(html)
port=re.compile('(.*?)')
re_port=port.findall(html)
foraddress,portinzip(re_ip_address,re_port):
address_port=address+':'+port
yieldaddress_port.replace('','')
定义了一个ProxyMetaclass,Crawl类将它设置为元类,元类中实现了new()方法,遍历attrs变量即可获取类的所有方法信息,判断方法名前面是否是crawl,是则将其加入到CrawlFunc属性中
代理网站的添加非常灵活,不仅可以添加免费代理,也可以添加付费代理,一些付费代理的提取方式类似,也通过Web的形式获取再进行解析,解析方式可能更加简单,如解析纯文本或Json,解析之后以同样的方式返回,可以自行扩展
utils.py
importrequests
fromrequests.exceptionsimportConnectionError
base_headers={
'User-Agent':'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/77.0.3865.120Safari/537.36',
'Accept-Encoding':'gzip,deflate,sdch',
'Accept-Language':'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'
}
defget_page(url,options={}):
headers=dict(base_headers,**options)
print('正在抓取',url)
try:
response=requests.get(url,headers=headers)
print('抓取成功',url,response.status_code)
ifresponse.status_code==200:
returnresponse.text
exceptConnectionError:
print('抓取失败',url)
returnNone
抓取网页内容的方法,访问链接成功后返回整个网页HTML内容,便于后续对网页具体内容的提取。封装成一个方法,让上面的crawler在抓取各个网站时调用
进行抓取
getter.py
fromcrawlerimportCrawler
fromsettingimport*
importsys
classGetter():
def__init__(self):
self.crawler=Crawler()
defrun(self):
print('获取器开始执行')
forcallback_labelinrange(self.crawler.__CrawlFuncCount__):
callback=self.crawler.__CrawlFunc__[callback_label]
#获取代理
all_ip=self.crawler.get_proxies(callback)
if__name__=='__main__':
get=Getter()
get.run()
运行结果:
网站上的免费IP就被成功抓取下来了,至于能不能用,就有待验证了
整个过程其实就是一个普通的爬虫,而且没什么反爬措施,能到用代理IP的地步,代码里面的访问、抓取部分的细节应该都看得懂
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。