爬虫代理IP池

1. 代码目标

因为需要进行一个大规模的爬取,具体是爬取全国地级以上城市的实时天气,历史某天到某天的天气,未来30天的天气,为了防止IP被封,需要使用代理IP进行爬取,而找了半天也没有找到好用的可以获取代理IP的库,所以就自己写了一个。流程大概是从免费代理IP 网站爬取IP,加入到IP池,并维护这个IP 池,在使用别的爬虫时,导入这个库,就可以使用代理IP爬取,适用于大规模爬虫。

2. 选取一个免费代理IP的网站

http://www.xicidaili.com/nn

3. F12查看网页结构

在这里插入图片描述
可以定位到 我们需要的IP地址和端口号在class=“clearfix proxies” 的 tr 标签中

4. 编写代码

导入库

# -*- coding: utf-8 -*-
import os
import time
import urllib.request
from bs4 import BeautifulSoup as BS
import requests

请求头

headers = ("User-Agent",
       "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 "
       "Safari/537.36")

opener对象

opener = urllib.request.build_opener()
opener.addheaders = [headers]
# 将opener安装为全局
urllib.request.install_opener(opener)

构建url并调用解析函数进行解析

url = "http://www.xicidaili.com/nn/1"
htmlsrc = urllib.request.urlopen(url).read().decode("utf-8")
bs = BS(htmlsrc, "html.parser")
ipInfo = ipParser(bs)

写入到文件

fn = filepath_filename+'.txt'  # IP池文件
f = open(fn, 'a')
for ip in ipInfo:
f.write(ip)
f.write('\n')

页面解析

htmlBody = bs.find('div', class_='clearfix proxies')
ip_list_1 = htmlBody.find_all('tr')
for i in range(1, len(ip_list_1)-1):
    container.append(ip_list_1[i].contents[3].text + ':' + ip_list_1[i].contents[5].text + ' '+str(0))
return container

5. 使用此库

导入

import scrapyIP as vIp

使用

vIp.scrapyIp(ipList_filepath_filename)
global overall_ip_list
overall_ip_list = vIp.readIp(ipList_filepath_filename + '.txt')

这样得到的ip表就是 overall_ip_list
需要注意的是,为了便于维护,我在每个ip后面增加了一个变量,用来表的可访问度
如下:
115.151.7.167:9999 0
110.52.235.6:9999 0
110.52.235.3:9999 0
初始化为0,在使用爬虫时,如果使用此代理IP访问目标网站失败,可访问度减1,成功就加1。

index = random.randint(0, len(overall_ip_list) - 1)
bsStr = overall_ip_list[index][0]

try:
    requests.get('网站url', proxies={"http": "http://%s" % (bsStr)}, timeout=30)
except:
    print('connect failed')  # 不能访问,继续选取
    # 对可访问做一个量化,越大表示越可访问,不可访问减1
    visit_degree = overall_ip_list[index][1]
    int_visit_degree = int(visit_degree)
    int_visit_degree = int_visit_degree - 1
    overall_ip_list[index][1] = int_visit_degree
    return randomGetIP(city)
else:
    print('success')
    visit_degree = overall_ip_list[index][1]
    int_visit_degree = int(visit_degree)
    int_visit_degree = int_visit_degree + 1
    overall_ip_list[index][1] = int_visit_degree
    print(bsStr)
    px = urllib.request.ProxyHandler({'http': '%s' % (bsStr)})
    return px

每隔一段时间,对小于一定值的IP进行清理

# 剔除目前ip表中可靠性低的ip
i = 0
global overall_ip_list
while i < len(overall_ip_list):
    if int(overall_ip_list[i][1]) < -5:  # 可靠性低于-5
        overall_ip_list.pop(i)
        i -= 1
    i += 1
# 将目前的ip表写入到文件,覆盖之前的
fr = open(iplist_filepath_filename + '.txt', 'w')
for ip0 in overall_ip_list:
    fr.write(str(ip0[0]) + ' ' + str(ip0[1]))
    fr.write('\n')
fr.close()
# 爬取ip并追加写入到文件
vIp.scrapyIp(iplist_filepath_filename)
# 读取文件为IP表
overall_ip_list = vIp.readIp(iplist_filepath_filename + '.txt')

代码下载地址:
点我