Skip to content

实战记录 | 抓取免费代理信息

约 163 个字 103 行代码 预计阅读时间 2 分钟

实战目标

获取免费代理信息网站前20页内的IP,Port,Location与检查时间等信息,提取站点的URL是https://www.kuaidaili.com/free/inha/

实现代码

# 导入所需的库
import requests, re  # requests用于发送HTTP请求,re用于正则表达式匹配
import time, random  # time用于延时,random用于生成随机数
import pandas  # pandas用于数据处理和Excel文件操作
import os  # os用于文件路径操作

# 基础URL和目标网站的URL
baseurl = 'https://www.kuaidaili.com/free/inha/'
# 请求头,模拟浏览器访问
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
}
# 正则表达式模式,用于从HTML中提取代理信息
pattern = '\{"ip": "(.*?)", "last_check_time": "(.*?)", "port": "(.*?)", "speed": (.*?), "location": "(.*?)"\}'
# 编译正则表达式,设置re.S标志以支持多行匹配
regex_set = re.compile(pattern=pattern, flags=re.S)

# 自定义异常类,用于文件构建时的错误处理
class FileBuildError(Exception):
    def __init__(self, message, code):
        super().__init__(message)
        self.code = code

    def __str__(self):
        return f"{self.args[0]} (Error Code: {self.code})"

# 获取网页HTML内容
def GET_HTML(url):
    try:
        res = requests.get(url=url, headers=headers)
        if res.status_code == 200:
            return res.text
        else:
            return None
    except requests.RequestException as e:
        print(e)
        return None

# 构建Excel文件
def FileBuild(content, Filename):
    # 将提取的内容转换为字典
    dict = {
        'IP': [str(content[0])],
        'Port': [str(content[2])],
        'Location': [str(content[4]).encode('utf-8').decode('unicode_escape')],
        'Speed': [str(content[3]) + 'ms'],
        'last_check_time': [str(content[1])]
    }
    # 检查字典中的所有值是否都为真(非空)
    if not all(dict.values()):
        raise FileBuildError('Don\'t get enough value!', 666)

    data = pandas.DataFrame(dict)
    # 如果文件不存在,直接创建并写入数据
    if not os.path.isfile(Filename):
        data.to_excel(Filename, index=False, sheet_name='ProxiesMessage')
    else:
        # 如果文件存在,读取现有数据与新数据合并,将合并后的数据重新写入文件
        existing_data = pandas.read_excel(Filename, sheet_name='ProxiesMessage')
        combined_data = pandas.concat([existing_data, data], ignore_index=True)
        combined_data.to_excel(Filename, index=False, sheet_name='ProxiesMessage')

# 解析HTML内容
def Parse_HTML(html):
    results = re.findall(regex_set, html)
    return results

def main(page):
    # 构造目标URL
    url = baseurl + str(page)
    try:
        # 获取网页内容
        res = GET_HTML(url=url)
    except Exception as e:
        # 如果获取失败,打印错误信息
        print('Page ' + str(i) + ' gets unsuccessfully! Reason: ', e)

    try:
        # 解析网页内容并提取代理信息
        for item in Parse_HTML(res):
            # 将提取的代理信息写入Excel文件
            FileBuild(item, 'Proxies.xlsx')
    except FileBuildError as e:
        # 如果文件构建失败,打印错误信息
        print('Message of Page ' + str(page) + ' notes unsuccessfully! Reason: ', e)
    except Exception as e:
        # 如果发生其他异常,打印错误信息并返回False
        print('Message of Page ' + str(page) + ' notes unsuccessfully! Reason: ', e)
        return False
    else:
        return True

# 主程序入口
for i in range(1, 21):  # 遍历第1页到第20页
    # 随机延时,避免频繁请求被目标网站封禁
    time.sleep(random.uniform(500, 2500) / 1000)
    # 调用主函数处理当前页
    if main(i) == True:
        # 如果处理成功,打印成功信息
        print('Page ' + str(i) + ' is noted into the file successfully.')

# 所有任务完成后打印提示信息
print('All things have done.')

最终成果

下载Excel文件

总结反思

  • 本网页采用的是JS渲染,所有信息存储在一个JS下的数据中,相比起以前在html标签块内寻找信息而言,本次在源码中定位目标信息一开始没有头绪。
  • 学习一个合适的文件操作方法很重要,这样子才能存储爬下来的数据
  • 记得去学pandas库!