ip代理池的构建
1. 代理ip网站的选择
这里以百度搜索“代理ip”为关键词,搜索结果中返回的第一个非广告信息作为爬取ip信息的网站,如下,该信息网址:快代理官方网址
2. ip信息的爬取
2.1 网页翻页的规律探索
一般选取前2-4页进行网页url规律的查找,如下
u2 = 'https://www.kuaidaili.com/free/inha/2/'
u3 = 'https://www.kuaidaili.com/free/inha/3/'
u4 = 'https://www.kuaidaili.com/free/inha/4/'
由此就可以找到翻页网址url的规律了, 除了最后的数字跟随着网页页数发生变化之外,其余的并没有发生改变
2.2 框架搭建
还是熟悉的感觉,进行常用库的导入,为了防止爬取的频率过快,引用time库进行程序间歇式爬取数据,基本上两个函数加上一个接口就可以完成框架的搭建。
其中接口提供的是要爬取的ip的页数(一页有20个ip信息),然后两个函数,第一个是解析页面的,第二个是获取ip信息的
import requests
from bs4 import BeautifulSoup
import time
headers = {
'Referer': 'https://www.kuaidaili.com/free/inha/1/',
'Cookie': '_ga=GA1.2.1075258978.1586877585; _gid=GA1.2.304073749.1587691875; ',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
} #这里的refer,cookie和header加上自己浏览器的即可
def get_ip(url):
html = requests.get(url,headers)
if html.status_code == 200:
print('正在爬取中...')
time.sleep(2)
parse_html(html.text)
else:
print('Error',url)
def parse_html(text):
pass
if __name__ == '__main__':
num = eval(input('请输入要爬取的页数:'))
for i in range(1,num + 1):
url = f'https://www.kuaidaili.com/free/inha/{i}/'
get_ip(url)
3. ip信息的爬取
刚刚框架已经搭建完成,主要的就是解析页面中内容的设计,如下
def parse_html(text):
soup = BeautifulSoup(text,'lxml')
ips = soup.select('#list tbody tr')
for line in ips:
ip = line.select_one('td').text
port = line.select('td')[1].text
print(f'Ip:{ip},Port:{port}')
→ 输出的结果为:(先进行第一页ip信息的爬取,进行程序试错)
4. 验证ip有效性
这里就是对框架进行功能函数的扩充,为了验证ip是否有效,可以封装一个测试函数,进行某一网站信息的爬取(这里以百度网站进行爬取验证,并设置反应时间为3s,如果3s内没有反应,则是无效)
#这几句代码是接在上面的print输出后面的,将ip和port组成可用的地址
#最后将地址加载到代理里面传入到验证ip函数中
address = f'http://{ip}:{port}'
proxies = {
'http':address,
'https':address
}
verify_ip(proxies)
def verify_ip(proxies):
try:
html = requests.get('http://www.baidu.com',proxies = proxies,timeout = 3)
print(f'[SUCCESS]可用代理:{proxies}')
except :
print(f'[ERROR]代理不可用:{proxies}')
→ 输出的结果为:(返回的结果中是包含可以使用的ip信息的,虽然失效率很高,但是也是可以白嫖到的)
5. 将有效ip信息保存至本地
由上的输出可以发现,还是有可以使用的信息的,为了方便今后爬虫的调用,可以将有效信息保存在本地,因此可以封装一个函数,进行有效ip信息的追加储存,如下
#这条语句是要在 print(f'[SUCCESS]可用代理:{proxies}')后面,调用存储ip信息的函数
save_ip(proxies)
#封装函数
def save_ip(proxies):
with open('ip_text.txt','a+') as f:
f.write(str(proxies)+'\n')#写入文本的时候,要以字符串的方式写入
print('\n[SUCCESS]代理已经写入文本!!!')
→ 输出的结果为:
6. 代理ip读取有效性检测
因为免费代理ip的时效性,爬取时有效的ip信息,当再次调用的时候,不一定生效,所以为了避免这种情况,可以在框架的基础上添加上读取代理ip信息的有效验证,这样再调取本地代理ip信息的时候就可以直接使用了
def read_txt():
with open('ip_text.txt','r',encoding='utf-8') as f:
contents = f.readlines()
for content in contents:
print(content) #这里输出的还是字符串类型,存入的是字符串,读取的自然也是
→ 输出的结果为:(爬取5页的信息,最后返回的只有5个可以使用)
测试验证,如下,代码是接在上面的print语句之后的,注意一下,读取的信息是字符串,而传递到proxies参数上的应该是字典类型,所以这里可以使用eval函数,将字符串转化为字典类型
try:
html = requests.get('http://www.baidu.com', proxies=eval(content), timeout=3)
print('[SUCCESS]有效代理',content)
except:
print('[ERROR]失效代理',content)
→ 输出的结果为:(经过一段时间后再测试,还有3条代理是至今可用的)
7. 全部代码
import requests
from bs4 import BeautifulSoup
import time
headers = {
'Referer': 'https://www.kuaidaili.com/free/inha/1/',
'Cookie': '_ga=GA1.2.1075258978.1586877585; _gid=GA1.2.304073749.1587691875; Hm_lvt_7ed65b1cc4b810e9fd37959c9bb51b31=1586877585,1587691875; channelid=0; sid=1587690934346679; Hm_lpvt_7ed65b1cc4b810e9fd37959c9bb51b31=1587692242',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
def get_ip(url):
html = requests.get(url,headers)
if html.status_code == 200:
print('正在爬取中...')
time.sleep(2)
parse_html(html.text)
else:
print('Error',url)
def parse_html(text):
soup = BeautifulSoup(text,'lxml')
ips = soup.select('#list tbody tr')
for line in ips:
ip = line.select_one('td').text
port = line.select('td')[1].text
print(f'[INFO]获取Ip:{ip},Port:{port}......')
address = f'http://{ip}:{port}'
proxies = {
'http':address,
'https':address
}
verify_ip(proxies)
def verify_ip(proxies):
try:
html = requests.get('http://www.baidu.com',proxies = proxies,timeout = 3)
print(f'[SUCCESS]可用代理:{proxies}')
save_ip(proxies)
except :
print(f'[ERROR]代理不可用:{proxies}')
def save_ip(proxies):
with open('ip_text.txt','a+') as f:
f.write(str(proxies)+'\n')
print('\n[SUCCESS]代理已经写入文本!!!')
def read_txt():
with open('ip_text.txt','r',encoding='utf-8') as f:
contents = f.readlines()
for content in contents:
# print(content)
try:
html = requests.get('http://www.baidu.com', proxies=eval(content), timeout=3)
print('[SUCCESS]有效代理',content)
except:
print('[ERROR]失效代理',content)
if __name__ == '__main__':
num = eval(input('请输入要爬取的页数:'))
for i in range(1,num + 1):
url = f'https://www.kuaidaili.com/free/inha/{i}/'
get_ip(url)
# read_txt()
#如果要验证读取代理ip的有效性,可以把read_text()语句前面的四行注释掉,调用read_text()函数即可
8. 拓展
如果觉得以字符串的形式保存代理ip信息后有需要以字符串形式的方式读取,最后使用还需转字典,过程太过复杂,可以直接将获取的address变量以字典的形式直接存储在本地,那么读取的时候自然也就是字典的格式,不需要再进行转化了,如下
8.1 json数据写入
# 写入json数据
def save_ip(proxies):
# with open('ip_text.txt','a+') as f:
# f.write(str(proxies)+'\n')
# print('\n[SUCCESS]代理已经写入文本!!!')
with open('ip_text.json','a+',encoding='utf-8') as f:
d = json.dumps(proxies)
f.write(d + '\n')
print('\n[SUCCESS]代理已经写入文本!!!')
→ 输出的结果为:(还是爬取五页)
8.2 json数据读取
def read_txt():
# with open('ip_text.txt','r',encoding='utf-8') as f:
# contents = f.readlines()
# for content in contents:
# print(content)
with open('ip_text.json','r' , encoding='utf-8') as f:
for line in f:
try:
content = json.loads(line.strip())
#print(content)
html = requests.get('http://www.baidu.com', proxies=content, timeout=3)
print('[SUCCESS]有效代理',content)
except:
print('[ERROR]失效代理',content)
→ 输出的结果为:(经过一段时间测试后,只有一个有用了,而且最后一个网址还引发了报错)