Python循环网页爬取遭Google封禁问题及批量爬取方案咨询
解决Google缓存爬取封禁问题并实现批量数据获取
问题根源
你触发了Google的反爬机制,批量高频请求被判定为异常流量导致IP封禁。同时原代码存在几个逻辑问题:
get_data函数定义在循环内部,每次循环重复定义完全冗余- 直接赋值
df_clean['BornDate']会覆盖所有行数据,无法对应单条链接的记录 - 读取的链接可能带换行符,导致请求URL无效
核心解决方案
1. 替换爬取目标:直接访问ATP官网而非Google缓存
Google缓存的反爬规则极其严格,而ATP官网的反爬限制相对宽松,直接爬取目标网站能从根源降低封禁概率。
2. 反爬规避措施
- 随机请求延迟:每次请求后随机等待1-3秒,模拟人类访问节奏
- 轮换User-Agent:准备多个不同设备/浏览器的UA标识,每次请求随机选取
- 异常捕获与重试:对请求失败的链接做容错处理,避免中断整个爬取任务
- 分批次控频:每处理一定数量的链接后额外延长等待时间,降低请求密度
3. 优化后的完整代码
import requests from bs4 import BeautifulSoup import time import random import pandas as pd # 准备多组User-Agent,模拟不同客户端 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/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15", "Mozilla/5.0 (Linux; Android 13; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Mobile Safari/537.36", "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1" ] def get_player_birthday(link): # 随机选取UA hdr = {"User-Agent": random.choice(USER_AGENTS)} try: req = requests.get(link, headers=hdr, timeout=10) req.raise_for_status() # 主动抛出HTTP错误 soup = BeautifulSoup(req.text, 'html.parser') birthday_elem = soup.select_one('.table-big-value-birthday') return birthday_elem.text.strip() if birthday_elem else None except Exception as e: print(f"请求失败 {link}: {str(e)}") return None # 读取链接文件,清理换行符与空行 with open('unique_links.txt', 'r') as file: links = [line.strip() for line in file if line.strip()] # 存储链接与生日的对应关系 birthday_data = {} for idx, link in enumerate(links, 1): print(f"处理第 {idx}/{len(links)} 条链接: {link}") birthday = get_player_birthday(link) birthday_data[link] = birthday # 基础随机延迟 time.sleep(random.uniform(1, 3)) # 每处理20条额外延长等待 if idx % 20 == 0: time.sleep(random.uniform(3, 5)) # 将结果匹配到数据集(假设df_clean有'player_link'列存储球员链接) df_clean['BornDate'] = df_clean['player_link'].map(birthday_data) # 保存爬取失败的链接,方便后续重试 failed_links = [link for link, bd in birthday_data.items() if bd is None] with open('failed_links.txt', 'w') as f: f.write('\n'.join(failed_links))
额外注意事项
- 如果ATP官网也出现封禁,可以尝试使用代理IP池,免费代理稳定性较差,付费代理更可靠
- 不要一次性爬完1662条,可分多天分批爬取,进一步降低反爬触发概率
- 遵守ATP官网的
robots.txt规则,球员页面属于允许爬取的范围
内容的提问来源于stack exchange,提问作者simao-af
相关产品推荐
相关产品推荐

