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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。