自建代理ip池
前言
为什么需要使用ip池?
当使用爬虫时,爬取一般的网站或者少量数据时,一些简单的爬虫就可实现。但对于那些反爬机制设置很好的网站而言,一个ip在一段时间内访问过多就会被临时封掉,所以我们需要设置多个ip代理来爬取需要的数据。
网上的代理ip有很多,付费免费的都有,这里主要爬取了两个免费代理ip网站:快代理、66代理
正文
爬取ip数据
和平常爬虫一样,我们传入网址,然后分析返回的response,获取到我们需要的代表代理ip的数据,然后保存到本地,这里具体就不在赘述。
### 爬取快代理的ip数据
def get_ip_kdl(html):
ip_list = []
soup = BeautifulSoup(html,'html.parser')
tr_list = soup.select('tbody tr')
for tr in tr_list:
ip_dict = {}
td = tr.select('td')
ip_dict['ip'] = td[0].get_text() #ip
ip_dict['port'] = td[1].get_text() #端口
ip_dict['ip_type'] = td[3].get_text() #网络类型
ip_dict['speed'] = td[5].get_text() #响应速度
ip_list.append(ip_dict)
# print(ip_list)
return ip_list
def kdl():
url = 'https://www.kuaidaili.com/free/inha/'
html = get_response(url).text
ip_list = get_ip_kdl(html)
return ip_list
###
def get_ip_66(html):
ip_list = []
soup = BeautifulSoup(html, 'html.parser')
tr_list = soup.find_all('div',attrs={'align':'center'})[1].select('table tr')
# print(tr_list)
for tr in tr_list[1:]:
ip_dict = {}
ip_dict['ip'] = tr.select('td')[0].get_text() # ip
ip_dict['port'] = tr.select('td')[1].get_text() # 端口
ip_dict['ip_type'] = None # 网络类型
ip_dict['speed'] = None # 响应速度
ip_list.append(ip_dict)
# print(ip_list)
return ip_list
def ip66():
url = 'http://www.66ip.cn/'
html = get_response(url).text
ip_list = get_ip_66(html)
return ip_list
这里使用的是第三方库BeautifulSoup,需要自己安装依赖包。当然也可使用python自带的正则来寻找数据,哪种使用熟练方便使用哪种。
保存至本地
我们所需要的数据只有IP和PORT字段,故可将其组合起来放入到txt文件中,方便复制使用;将IP、PORT、响应速度等保存为json文件,方便读取。
###保存至本地(具体保存地址自行修改)
#存为json
def save_json(ip):
ip_json = json.dumps(ip, ensure_ascii=False) + ",\n"
with open(r'C:\Users\15394\Desktop\ip池.json','ab') as f:
f.write(ip_json.encode('utf-8'))
#存为txt
def save_txt(ip):
ip_type = ip['ip_type']
port = ip['port']
str_ip = ip['ip']
if ip_type == None:
ip_txt = 'http://' + str_ip + ':' + port + '\n'
else:
ip_type = ip_type.lower()
ip_txt = ip_type + '://' + str_ip + ':' + port + '\n'
with open(r'C:\Users\15394\Desktop\ip池.txt','ab') as f:
f.write(ip_txt.encode('utf-8'))
判断ip有效性
ip数据爬取下来了,但由于是免费的,所以不能确定它的有效性,需要自己判断一下。
这里是使用代理ip去访问百度,若返回200的状态码,则表示此ip可用。
#判断ip是否有用
def useful(ip):
baidu_url = 'https://www.baidu.com/'
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",}
proxy = 'http://' + ip['ip'] + ':' + ip['port']
proxies = {'http':proxy}
response = requests.get(baidu_url,proxies=proxies,headers=headers)
if response.status_code == 200:
return True
else:
return False
也可访问http://icanhazip.com/来查看当前访问的ip。
全部代码
需自行安装requests、bs4依赖包
#!-*-coding:utf-8 -*-
# python3.7
# @Author:fuq666@qq.com
# Update time:2021.01.28
# Filename:爬取网上的免费ip来组成ip池(并判断是否有用)
import requests
from bs4 import BeautifulSoup
import json
def get_response(url):
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
}
response = requests.get(url,headers=headers)
if response.status_code == 200:
return response
else:
print("{}请求失败".format(url))
#快代理
def get_ip_kdl(html):
ip_list = []
soup = BeautifulSoup(html,'html.parser')
tr_list = soup.select('tbody tr')
for tr in tr_list:
ip_dict = {}
td = tr.select('td')
ip_dict['ip'] = td[0].get_text() #ip
ip_dict['port'] = td[1].get_text() #端口
ip_dict['ip_type'] = td[3].get_text() #网络类型
ip_dict['speed'] = td[5].get_text() #响应速度
ip_list.append(ip_dict)
# print(ip_list)
return ip_list
def kdl():
url = 'https://www.kuaidaili.com/free/inha/'
html = get_response(url).text
ip_list = get_ip_kdl(html)
return ip_list
#66ip
def get_ip_66(html):
ip_list = []
soup = BeautifulSoup(html, 'html.parser')
tr_list = soup.find_all('div',attrs={'align':'center'})[1].select('table tr')
# print(tr_list)
for tr in tr_list[1:]:
ip_dict = {}
ip_dict['ip'] = tr.select('td')[0].get_text() # ip
ip_dict['port'] = tr.select('td')[1].get_text() # 端口
ip_dict['ip_type'] = None # 网络类型
ip_dict['speed'] = None # 响应速度
ip_list.append(ip_dict)
# print(ip_list)
return ip_list
def ip66():
url = 'http://www.66ip.cn/'
html = get_response(url).text
ip_list = get_ip_66(html)
return ip_list
#判断ip是否有用
def useful(ip):
baidu_url = 'https://www.baidu.com/'
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",}
proxy = 'http://' + ip['ip'] + ':' + ip['port']
proxies = {'http':proxy}
response = requests.get(baidu_url,proxies=proxies,headers=headers)
if response.status_code == 200:
return True
else:
return False
#存为json
def save_json(ip):
ip_json = json.dumps(ip, ensure_ascii=False) + ",\n"
with open(r'C:\Users\15394\Desktop\ip池.json','ab') as f:
f.write(ip_json.encode('utf-8'))
#存为txt
def save_txt(ip):
ip_type = ip['ip_type']
port = ip['port']
str_ip = ip['ip']
if ip_type == None:
ip_txt = 'http://' + str_ip + ':' + port + '\n'
else:
ip_type = ip_type.lower()
ip_txt = ip_type + '://' + str_ip + ':' + port + '\n'
with open(r'C:\Users\15394\Desktop\ip池.txt','ab') as f:
f.write(ip_txt.encode('utf-8'))
def main():
ip_list_kdl = kdl()
ip_list_66 = ip66()
# ip_list_gbj = gbj()
ip_list = ip_list_kdl + ip_list_66
for ip in ip_list:
if useful(ip): #有效的ip
save_json(ip)
save_txt(ip)
else:
pass
if __name__ == '__main__':
main()
注:
- 上面两个免费的ip网站随时可能无妨访问,所以平时可多积累几个类似的网站,或者使用付费的ip网站,效果更好。
- 爬取下来的ip仅仅代表当前可用,随时可能失效,所以在需要使用的时候再进行爬取。并且,在使用这些代理ip进行爬虫时,也可能已经处于失效状态。查看ip是否可用,可在电脑终端ping ip,若能ping通,则表示有效。
- 最好在学习之时,才使用免费代理ip。
其他
如何在爬虫中使用代理ip
-
使用requests库进行爬虫
import requests proxies = {'http':'http://localhost:8888','https':'http://localhost:8888'} response = requests.get(url,proxies=proxies,verify=False) #可将代理ip放入列表中,然后使用random.choice随机选取一个ip,再变为字典,传入requests -
使用scrapy框架进行爬虫
-
ip池的存放
ip池可以列表形式存于settings.py中,也可放置于中间件middlewares.py文件中。
IPPOOL = [ {"ipaddr":"115.221.245.137:9999"}, {"ipaddr":"175.42.128.86:9999"}, ] -
使用ip
ip的使用是在中间件middlewares.py文件中。
import random #ip池 class ippool(Object): def __init__(self,ip=''): self.ip = ip def process_request(self,request,spider): use_ip = random.choice(IPPOOL) # print('当前ip是:',use_ip["ipaddr"]) request.meta["proxy"] = "http://" + use_ip["ipaddr"]还需要在settings.py文件中打开这个中间件的注释
DOWNLOADER_MIDDLEWARES = { # 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 100, 'JD.middlewares.ippool':150, }注:当ip池IPPOOL放在settings.py文件中时,还需要在middlewares.py中引用他。
from JD.settings import IPPOOL
-
遇上方知有

浙公网安备 33010602011771号