Python简易实现IP代理池及其维护
用处
通过自己购买或爬取到的ip,在程序中使用这些ip进行代理,达到绕过反爬虫机制的效果以及其他用途。
思路
从各大免费的ip网站抓取ip,存入数据库,使用时按序取出使用。注:存入及使用前先验证ip是否可用
我们在这里使用 西刺 这里网站里的免费ip,数据库使用mongodb
使用到的库
request
re
json
结构
IpPool
panel
Code
init.py
我们在这个文件中写一个爬虫的基类,方便我们拓展不同的网站
"""ipSpider Class"""
importrequests
importpymongo
importconfig
db=pymongo.MongoClient(config.db_host)[config.db_name]
classIpSpiderWeb:
"""网页抓取 基类"""
def__init__(self,timeout,time_interval,url):
self.timeout=timeout
self.url=url
defget_html(self,url,headers=None,data=None):
"""获取html页面"""
print('Getting html...')
try:
response=requests.get(
url=url,
headers=headers,
data=data,
timeout=self.timeout
)
exceptExceptionase:
print('![ERROR][GET_HTML] %s'%e)
else:
print('*[SUCCESS][GET_HTML]')
returnresponse.text
defcheck_ip(self,ip):
test_url="https://httpbin.org/get"
proxy= {
'https':ip['ip'],
'http':ip['ip']
}
try:
re=requests.get(
url=test_url,
proxies=proxy,
timeout=self.timeout)
exceptExceptionase:
print('-[FAIL]'+proxy['https'])
returnFalse
ifre.status_code==200:
print('*[OK]'+proxy['https'])
returnTrue
else:
print('-[FAIL]'+proxy['https'])
returnFalse
defsave_to_db(self,ip):
"""保存至数据库"""
print('ip saving...',end="")
ifdb["ipPool"].find(ip).count():
print('exist')
return
else:
db["ipPool"].insert(ip)
print('ok')
defget_ip(self,end_index):
"""入口"""
pass
defprams_html(self,url,page_index):
""" 处理 html数据"""
pass
config.py
在这里我们放一些参数,方便我们配置程序
# 数据库
db_host="mongodb://localhost:27017/"
# 数据库名
db_name="IpPool"
# 超时重试
time_out=3
mian.py
importpymongo
importconfig
importtime
db=pymongo.MongoClient(config.db_host)[config.db_name]
# panel 是我们接入网站是写的类, num是我们爬去的页数
defprocess(panel,num):
ip_spider=panel.Spider(config.time_out,support.ip_url)
ip_spider.get_ip(num)
# 检查数据库中 ip 的数量
defcheck_ip_num():
ifdb["ipPool"].find().count()
returnTrue
returnFalse
if__name__=="__main__":
whileTrue:
ifcheck_ip_num():
pass
else:
time.sleep(3)
上面就是这个ip爬取的主要框架,接下来开始接入西刺这个网站,在panel文件夹中新建文件 XICI.py
from.importIpSpiderWeb
frombs4importBeautifulSoup
# 这里是目标网站,ip列表的地址
ip_url="http://www.xicidaili.com/nn/"
# 因为爬虫访问西刺,如果不设置 headers,网站会屏蔽访问
headers= {
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate',
'Accept-Language':'zh-CN,zh;q=0.9',
'Cache-Control':'max-age=0',
'Connection':'keep-alive',
'Cookie':'_free_proxy_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJTJmZTQ3OTBmNDdlZjdiM2RjNWFlZmMzMTU1NWFiMzA4BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMWJmTnEwQmlQQmtadnl3RzZEdTNzemlWQmFCMEc0TGRvcXNPV2R2U2R3STQ9BjsARg%3D%3D--416e4f5df96bdaffab52ef2eecbcc04cb7b774fc; Hm_lvt_0cf76c77469e965d2957f0553e6ecf59=1537326605; Hm_lpvt_0cf76c77469e965d2957f0553e6ecf59=1537334978',
'Host':'www.xicidaili.com',
'If-None-Match':'W/"eb659eef9c5b25d4c83d43381a66cd6d"',
'Upgrade-Insecure-Requests':'1',
'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
classSpider(IpSpiderWeb):
"""xici ip"""
defget_ip(self,end_index):
foriinrange(1,end_index+1):
print("正在抓取第%d页"%i)
self.prams_html(self.url,i)
defprams_html(self,url,page_index):
tar_url=url+str(page_index)
html=self.get_html(
tar_url,
headers,
data=None
)
# 根据页面的结构,抓取数据,在这里也可以使用xpath或者正则表达式
try:
bs=BeautifulSoup(html,'lxml')
res=bs.find_all('tr')
exceptExceptionase:
print("[ERROR] %s"%e)
return
foriteminres:
temp= {}
try:
tds=item.find_all('td')
iftds[5].textin['HTTPS','HTTP']:
temp['ip'] =tds[1].text+":"+tds[2].text
exceptIndexError:
pass
#检查ip是否可用前先判断是否拿到数据
iftemp:
ifself.check_ip(temp):
self.save_to_db(temp)
再回到 main.py 使用process()函数开始爬虫
main.py
frompanelimportXICI
......
if__name__=="__main__":
whileTrue:
ifcheck_ip_num():
process(XICI,5)
else:
time.sleep(3)
......
ip池的使用
我们可以在使用时先从数据库中将所有 ip 取出,安装队列的形式或者列表随机抽取的形式进行维护,当ip不可用时,从数据库中删除该ip,当出现ip被封时放回队列或者列表,这里不做过多的介绍。
领取专属 10元无门槛券
私享最新 技术干货