Python批量爬取Google Shopping多商品时数据不全如何解决?
问题根因
- 变量名冲突:外层遍历商品列表的
product变量,在内层提取商品信息时被重复赋值为商品名称字符串,虽然不会直接导致请求失败,但会引发逻辑隐患 - User-Agent过于陈旧:你使用的是多年前的Edge 18版本UA,Google很容易识别为爬虫请求,直接返回反爬验证页面而非正常的商品搜索结果
- 缺少响应校验逻辑:没有判断请求是否成功、返回内容是否为正常的搜索结果页,直接解析页面会因为找不到目标元素返回空数据
- 固定延迟策略容易被识别:固定10秒延迟的规律性很强,无法有效绕过反爬策略
- 无会话保持:每次请求都是独立的,没有携带Cookie信息,更容易触发Google的反爬校验
修复方案
核心修改点
- 修正变量名冲突,内层商品名称变量改为
product_title避免覆盖 - 引入随机User-Agent池,每次请求随机切换UA
- 使用
requests.Session()保持会话,自动管理Cookie - 添加响应状态码校验、目标元素存在性校验,搭配重试机制
- 采用随机延迟模拟真实用户访问行为
修复后代码
from time import sleep from random import randint, choice import requests from bs4 import BeautifulSoup # 新增UA池,可自行补充最新的浏览器UA USER_AGENTS = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/118.0.2088.69 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15" ] stores = ["Submarino", "Casas Bahia", "Extra.com.br", "Americanas.com", "Pontofrio.com", "Shoptime", "Magazine Luiza", "Amazon.com.br - Retail", "Girafa"] products = [ { "name" : "Console Playstation 5", "lowestPrice" : 4000.0, "highestPrice" : 4400.0 }, { "name" : "Controle Xbox Robot", "lowestPrice" : 320.0, "highestPrice" : 375.0 } ] # 初始化会话保持Cookie session = requests.Session() max_retry = 3 # 单请求最大重试次数 for product in products: params = {"q": product["name"], 'tbm': 'shop'} retry_count = 0 success = False while retry_count < max_retry and not success: # 随机选UA headers = { "User-Agent": choice(USER_AGENTS) } try: response = session.get("https://www.google.com/search", params=params, headers=headers, timeout=10) response.raise_for_status() # 状态码非200直接抛异常走重试 soup = BeautifulSoup(response.text, 'lxml') shopping_results = soup.select('.sh-dgr__content') if not shopping_results: # 没找到目标元素,大概率触发反爬,重试 retry_count +=1 sleep(randint(3,8)) continue # 正常解析 for shopping_result in shopping_results: # 变量名改为product_title避免冲突 product_title = shopping_result.select_one('.Lq5OHe.eaGTj h4').text price = shopping_result.select_one('span.kHxwFf span.a8Pemb').text store = shopping_result.select_one('.IuHnof').text link = f"https://www.google.com{shopping_result.select_one('.Lq5OHe.eaGTj')['href']}" if store in stores: print(product_title) print(price) print(store) print(link) print() print() success = True except Exception as e: retry_count +=1 sleep(randint(3,8)) print('####################################################################################################################################################') # 两次商品查询之间加随机延迟 sleep(randint(2,6))
如果修改后依然有部分请求失败,可以将response.text打印出来查看返回内容,确认是否触发了人机验证,这种场景下可以考虑添加代理池进一步降低被封锁的概率。
内容的提问来源于stack exchange,提问作者churros
相关产品推荐
相关产品推荐

