使用Requests和BS4爬取Reddit链接时有时返回空列表的问题
为啥爬取结果时好时坏?
1. 被Reddit反爬机制盯上了
直接用requests.get发请求,没带任何浏览器标识,Reddit很容易识别出这是爬虫,会返回一个仅含JS框架的空页面(BeautifulSoup解析不了JS动态加载的内容),自然拿不到链接。偶尔成功可能是反爬策略的随机性,或是当时你的IP没被限制。
2. 依赖的类名是动态生成的
代码里用的SQnoC3ObvgnGjWt90zD9Z _2INHSNB8V5eaWp4P0rY_mE这类类名,是Reddit前端动态生成的,前端一更新,这个类名就会失效,靠它定位元素根本不稳定。
怎么解决?
方案1:模拟浏览器请求+稳定选择器
给请求加User-Agent头伪装成真实浏览器,同时换用基于链接特征的选择器,摆脱对动态类名的依赖。
修改后的代码:
import requests from bs4 import BeautifulSoup base_url = 'https://www.reddit.com/r/AskReddit/top/?t=day' # 替换成你自己浏览器的User-Agent,搜"我的User-Agent"就能查到 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' } r = requests.get(base_url, headers=headers) soup = BeautifulSoup(r.text, 'html.parser') links = [] # 匹配所有href以/r/AskReddit/comments开头的a标签,同时去重 for link in soup.find_all('a', href=True): if link['href'].startswith('/r/AskReddit/comments/') and link['href'] not in links: print(link['href']) links.append(link['href']) print(links)
方案2:用Reddit官方API(最稳定)
直接调用API获取数据,既不会触发反爬,也不用操心页面结构变化。需要先去Reddit开发者平台创建应用,拿到client_id和client_secret。
示例代码:
import requests # 替换成你自己的应用信息 client_id = '你的client_id' client_secret = '你的client_secret' user_agent = '你的应用名称/1.0' # 获取访问令牌 auth = requests.auth.HTTPBasicAuth(client_id, client_secret) data = {'grant_type': 'client_credentials'} headers = {'User-Agent': user_agent} res = requests.post('https://www.reddit.com/api/v1/access_token', auth=auth, data=data, headers=headers) token = res.json()['access_token'] headers['Authorization'] = f'bearer {token}' # 请求每日热榜数据 res = requests.get('https://oauth.reddit.com/r/AskReddit/top/?t=day', headers=headers) links = [] for post in res.json()['data']['children']: link = post['data']['permalink'] print(link) links.append(link) print(links)
注意事项
- 不要频繁发送请求,否则可能被Reddit封禁IP,建议添加
time.sleep(1)这类请求间隔。 - 使用API时,要遵守Reddit的API调用配额限制,避免触发限流。
内容的提问来源于stack exchange,提问作者UnfunnySoy78
相关产品推荐
相关产品推荐

