Python爬虫:自建IP地址池

使用工具及网站:

网站:快代理
python版本:3.8.2
IDE:PyCharm Community Edition 2020.1 x64

新手(也包括我😁)在练习爬虫时总会拿一些网站来练手,不过,遇到某些网站,爬取过多可能会封掉你的 IP ,这可就麻烦了,所以构建自己的 IP地址池 时很重要的。
首先分析一下 快代理 网站:
在这里插入图片描述

通过查看网页源代码可以知道,该网站是一个静态网站,对于我们所要寻找的内容,都可以在网站的源代码中找到。

步骤:

首先,将我们所需的基本库全部导入:

import requests
import time
from bs4 import BeautifulSoup

构建一个请求函数:

def get_info(url):  # 请求网页(包含判断是否请求成功)
    try:
        r = requests.get(url, headers=header)
        r.raise_for_status()
        r.encoding = 'utf-8'  #网页源码中查找的编码。
        return r
    except:
        print('请求失败!')

获取并分析源码:

# <tr>
#     <td data-title="IP">36.249.49.38</td>
#     <td data-title="PORT">9999</td>
#     <td data-title="匿名度">高匿名</td>
#     <td data-title="类型">HTTP</td>
#     <td data-title="位置">福建省泉州市  联通</td>
#     <td data-title="响应速度">0.3秒</td>
#     <td data-title="最后验证时间">2020-04-29 10:31:01</td>
# </tr>
def get_ip_dict(url):
    soup = BeautifulSoup(get_info(url).text, 'html.parser')
    for info_list in soup.find_all('tr')[1:]:
        soup1 = BeautifulSoup(str(info_list), 'html.parser')
        #获取 IP 字段信息
        IP = soup1.find('td', attrs={'data-title': "IP"}).string
        #获取 PORT 字段信息
        PORT = soup1.find('td', attrs={'data-title': "PORT"}).string
        #获取 类型 字段信息
        TYPE = soup1.find('td', attrs={'data-title': "类型"}).string
        #将每一个IP信息都保存为字典的形式,ip_dict = {} 为群居变量。
        ip_dict[IP] = TYPE + '://' + IP + ':' + PORT
        #程序的爬取速度非常快,以致于网站服务器根本来不及反映,
        #所以会造成不同的异常出现。用休眠来等待服务器反应。
        time.sleep(0.1)

检查获取到的 IP 是否满足要求:
这里通过携带信息访问百度网站来检测。

def check_ip():  # 检查IP是否可用
	#由于字典在迭代过程中不能修改字典大小,所以迭代时转换为 list 类型。
    for IP in list(ip_dict.keys()): 
        try:
        	#  .get() 中的所有携带信息为字典类型。
            r = requests.get('https://www.baidu.com/', proxies={IP: ip_dict[IP]}, headers=header, timeout=0.1)
            r.raise_for_status()
        except:
        	#删除当前延时超过 0.1 秒的 IP 信息。
            del ip_dict[IP]
    print('已对所有IP进行检测,延时不超过 0.1 秒的有 {} 个。'.format(len(ip_dict)))

翻页操作:
有时,我们的要求过高时,一页的数据经过筛选后,可能不够我们使用,所以需要进行翻页操作(这里只翻了5页):

网页的页面信息如下:
https://www.kuaidaili.com/free/
https://www.kuaidaili.com/free/inha/2/
https://www.kuaidaili.com/free/inha/3/
https://www.kuaidaili.com/free/inha/4/

对于第一页的网址,也可以写成:
https://www.kuaidaili.com/free/inha/1/

def get_main_url():  # 翻页
    url = 'https://www.kuaidaili.com/free/'
    for page_num in range(1, 6):
        URL = url + 'inha/{}/'.format(page_num)
        get_ip_dict(URL)
    print('所有IP信息已准备就绪,共 {} 个。'.format(len(ip_dict)))

最后,主函数调用:

if __name__ == '__main__':
    get_main_url()
    check_ip()

源代码:

import requests
import time
from bs4 import BeautifulSoup

header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36 Edg/81.0.416.64'
}

ip_dict = {}  # 保存能够使用的IP完整形式


def get_info(url):  # 请求网页(包含判断是否请求成功)
    try:
        r = requests.get(url, headers=header)
        r.raise_for_status()
        r.encoding = 'utf-8'
        return r
    except:
        print('请求失败!')


# <tr>
#     <td data-title="IP">36.249.49.38</td>
#     <td data-title="PORT">9999</td>
#     <td data-title="匿名度">高匿名</td>
#     <td data-title="类型">HTTP</td>
#     <td data-title="位置">福建省泉州市  联通</td>
#     <td data-title="响应速度">0.3秒</td>
#     <td data-title="最后验证时间">2020-04-29 10:31:01</td>
# </tr>
def get_ip_dict(url):
    soup = BeautifulSoup(get_info(url).text, 'html.parser')
    for info_list in soup.find_all('tr')[1:]:
        soup1 = BeautifulSoup(str(info_list), 'html.parser')
        IP = soup1.find('td', attrs={'data-title': "IP"}).string
        PORT = soup1.find('td', attrs={'data-title': "PORT"}).string
        TYPE = soup1.find('td', attrs={'data-title': "类型"}).string
        ip_dict[IP] = TYPE + '://' + IP + ':' + PORT
        time.sleep(0.1)


def check_ip():  # 检查IP是否可用
    for IP in list(ip_dict.keys()):
        try:
            r = requests.get('https://www.baidu.com/', proxies={'http': ip_dict[IP]}, headers=header, timeout=0.1)
            r.raise_for_status()
        except:
            del ip_dict[IP]
    print('已对所有IP进行检测,延时不超过 0.1 秒的有 {} 个。'.format(len(ip_dict)))


def get_main_url():  # 翻页
    url = 'https://www.kuaidaili.com/free/'
    for page_num in range(1, 6):
        URL = url + 'inha/{}/'.format(page_num)
        get_ip_dict(URL)
    print('所有IP信息已准备就绪,共 {} 个。'.format(len(ip_dict)))


if __name__ == '__main__':
    get_main_url()
    check_ip()

运行结果:

所有IP信息已准备就绪,共 75 个。
已对所有IP进行检测,延时不超过 0.1 秒的有 40 个。
 

代码交流 2020