使用BeautifulSoup爬取IMDB用户会员年限出现IndexError怎么解决?
问题根源
- 核心触发原因是IMDB的反爬机制:批量高频请求时,平台会直接返回拦截页面(验证码/403拒绝访问页),这类页面不存在你要匹配的
div.value元素,导致find_all返回空列表,取[-1]时直接触发索引越界。单次请求因为频率低未触发反爬,所以偶尔能正常返回结果。 - 次要潜在问题:部分用户页面可能无对应徽章、
html.parser解析容错性不足、请求头配置过于简单也可能导致匹配失败。
修复方案
- 先做基础合法性校验:先判断请求状态码是否为200,再判断匹配到的元素列表是否非空,异常情况统一返回占位标记(比如
None/'未知')避免程序直接崩溃。 - 批量请求时增加随机延迟:每次请求间隔1-3秒,降低触发反爬的概率。
- 完善请求头配置,使用
requests.Session维持会话上下文,模拟真实浏览器访问行为。 - 可替换为容错性更高的
lxml解析器(需提前安装lxml库)。
修复后代码示例
单个抓取函数修改
import requests import time import random from bs4 import BeautifulSoup # 初始化会话复用,减少被识别概率 session = requests.Session() session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 'Referer': 'https://www.imdb.com/' }) def getYear(review_url): try: # 随机延迟,也可以放到批量调用逻辑中调整 time.sleep(random.uniform(1, 3)) response = session.get(review_url, timeout=10) # 先校验请求是否成功 if response.status_code != 200: return '请求失败' # 用lxml解析,容错性更高 soup = BeautifulSoup(response.text, 'lxml') year_list = soup.find_all('div', attrs={'class': 'value'}) # 列表非空再取值 if year_list: return year_list[-1].get_text().strip() else: return '无匹配数据' except Exception as e: # 捕获所有异常避免批量调用中断 return f'异常:{str(e)}'
批量调用逻辑
可以保留原有写法,返回的列表里会自动标记失败的条目,后续可以单独对异常条目重试:
years = [getYear(url) for url in user_links]
如果后续反爬严格到返回验证码,可以额外配置代理池或者使用无头浏览器抓取。
内容的提问来源于stack exchange,提问作者Malvi Patel
相关产品推荐
相关产品推荐

