为何代码仅偶尔找到HTML对象?亚马逊评论数抓取异常求助
问题分析与优化方案
你的代码只有50%成功率的核心原因:
- 依赖
"with reviews"文本匹配太脆弱,亚马逊页面结构变动或反爬机制触发时,会返回不同内容,导致找不到目标元素。 - 完全没有异常处理逻辑,一旦元素找不到直接触发报错中断。
优化后的实现方案
核心改进点
- 改用亚马逊评论数的固定元素定位(比如
id="acrCustomerReviewText",这个元素通常直接显示评论数量文本,稳定性远高于文本匹配)。 - 添加浏览器请求头,降低被反爬拦截的概率。
- 增加异常捕获,处理元素找不到、请求失败等各种异常情况。
- 简化文本处理逻辑,无需依赖
html2text,直接提取数字即可。
优化代码
from requests_html import HTMLSession from bs4 import BeautifulSoup import re import time def get_amazon_review_count(product_review_url): s = HTMLSession() # 模拟浏览器请求头,避免被识别为爬虫 headers = { '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' } try: r = s.get(product_review_url, headers=headers) # 若页面是动态加载(比如评论数由JS渲染),启用下面的渲染方法(可选) # r.html.render(sleep=1, timeout=10) soup = BeautifulSoup(r.content, "html.parser") # 优先用固定ID定位评论数元素 review_count_elem = soup.find(id="acrCustomerReviewText") if not review_count_elem: # 备用方案:匹配包含评论数的文本内容 review_count_elem = soup.find(string=re.compile(r'\d+[\s,]*reviews?')) if review_count_elem: # 提取文本并清洗数字 review_text = review_count_elem.get_text(strip=True) # 匹配所有数字部分,处理带逗号的千位分隔符 num_match = re.search(r'(\d[\d,]*)', review_text) if num_match: review_num = num_match.group(1).replace(',', '') return int(review_num) print("无法定位评论数量,可能页面结构变化或被反爬拦截") return None except Exception as e: print(f"请求或解析出错: {str(e)}") return None # 测试调用 url = 'https://www.amazon.com/product-reviews/B07V37GVY9?pageNumber=1' # 添加请求间隔,降低反爬风险 time.sleep(2) review_count = get_amazon_review_count(url) if review_count: print(f"评论数量: {review_count}")
额外注意事项
- 亚马逊反爬机制严格,频繁请求会被限制IP,建议每次请求间隔2-5秒。
- 如果遇到验证码页面,需要手动验证或使用代理IP轮换。
- 页面结构可能随时间更新,若
id="acrCustomerReviewText"失效,需重新查看页面源码找新的定位标识(比如特定class)。
内容的提问来源于stack exchange,提问作者BKANE
相关产品推荐
相关产品推荐

