使用Python爬虫,基于本地IP直接向网站发送请求以爬取数据时,可能由于网站的反爬措施而导致IP封禁。特别是在课堂演示等场景下,多台主机多次在同一IP发送请求,很难不出现这样的问题。这里以豆瓣电影Top250的爬取为例,对问题进行解析,并提供一种基于IP代理的解决方案。

问题描述

代码见:https://github.com/AWildFunny/IP-ProxyCrawler-for-doubanTop250/blob/main/web_crawler.py,为课堂上使用的演示代码,来源不详。

执行代码时,大多数同学的Python控制台出现“403 Forbidden”错误,说明请求不成功,豆瓣服务器没有正常返回一个网页。随后程序报错:

Traceback (most recent call last):
  File "D:\Desktop\学校课程\数据分析方法与工具\web_crawler.py", line 156, in <module>
    main()
  File "D:\Desktop\学校课程\数据分析方法与工具\web_crawler.py", line 29, in main
    saveData(datalist,savepath)      #2种存储方式可以只选择一种
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "D:\Desktop\学校课程\数据分析方法与工具\web_crawler.py", line 105, in saveData
    data = datalist[i]
           ~~~~~~~~^^^
IndexError: list index out of range

这里的原因是:由于在askURL函数中request方法没有成功请求到网页,导致第39行代码返回的html为空,因此getData函数的返回值datalist为空,最终在saveData函数保存文件时代码第103行循环访问了空的datalist,导致列表越界(list index out of range)。

原因分析

根本原因在于:豆瓣网页设计了反爬虫逻辑,每个IP在多次请求(一般是50次左右)网页后就会遭封禁,一般48h左右解除。这时,访问豆瓣网页时会跳出如下的提示:

Snipaste_2024-11-15_21-18-39.png

要解决这一问题有多个思路:

  1. 更换IP,比如从校园网切换为流量
  2. 若1.依旧不行,则可使用代理IP
  3. 使用模拟用户访问网页的爬虫方法(较复杂)

这里以思路2.为例,对代码进行修改,并演示使用代理IP的爬虫方法:

解决方案:基于IP代理的爬虫方法

首先代码进行以下几处修改:

修改后的完整代码见:https://github.com/AWildFunny/IP-ProxyCrawler-for-doubanTop250/blob/main/web_crawler_new.py

在使用时,首先需要获取一个代理服务器,这里以“蜻蜓代理”的免费试用服务为例:

  1. 首先访问网站注册账号,见https://proxy.horocn.com/
  2. 选择“隧道代理IP”进行免费试用(如下图),需要首先进行身份验证

Snipaste_2024-11-15_22-37-51.png

  1. 开通成功后,在用户中心→隧道代理可以查看订单,如下:

Snipaste_2024-11-15_22-40-09.png

将复制的订单号、密码分别填入程序中下面对应的部分(修改后的代码第24-28行):

# 添加代理服务器配置
proxyHost = "dyn.horocn.com"
proxyPort = "50000"
proxyUser = "你的订单号"  # 替换为你的订单号
proxyPass = "你的密码" # 替换为你的密码
  1. 再次运行程序,此时会使用代理服务器发送请求,并不断尝试,直到完整爬取所有结果。若再次报错,可能是代理服务器的费用到期了。

讨论延伸

除豆瓣以外,如今的大部分网站,无论是社交媒体还是电商,都设置了大量的反爬取措施。在不使用“用户操作模拟”方法的前提下,在传统的爬虫方法上,要绕开反爬取逻辑就需要尽可能:

同时,这种方式依赖第三方的代理服务器,也就是有费用成本的。在尝试采用网上的免费代理IP时,几乎全部都超时无法使用。是否有更加简单的方法,能够避开类似网站的反爬虫逻辑呢?

References: