You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用grequests高效批量请求Glassdoor评论页?规避403并提速

Glassdoor评论爬取优化问题

我需要爬取Glassdoor上某公司的所有评论页面,部分公司的评论页面可达数千页。尝试用grequests批量请求时,单次发送超过约100个请求就会收到403错误。

于是我写了如下代码,把请求按每100个一批处理:

import math
import time
from random import uniform
import grequests

reviews_url = "https://www.glassdoor.com/Reviews/Apple-Reviews-E1138.htm?"
DEFAULT_HEADERS = {
    # 你的请求头配置
}

batch = 100
responses = []
for j in range(math.ceil(num_pages/batch)):
    print("Batching requests: {}/{}".format(min(num_pages, (j+1)*batch), num_pages))
    rs = (
        grequests.get(
            reviews_url.replace(".htm", "_P" + str(k + 1) + ".htm"),
            headers=DEFAULT_HEADERS,
        )
        for k in range(min(num_pages, j*batch), min(num_pages, (j+1)*batch))
    )
    responses += grequests.map(rs)
    time.sleep(uniform(10,15))

这个方案能正常获取数据,但速度太慢,我要处理约8000家公司的评论页。缩短批次间休眠时间又会触发403,有没有更优的实现方法?


优化方案
  • 精细化控制请求速率
    不要固定100个请求为一批,试试更小的批次(20-50个),同时给批次内的每个请求添加随机小间隔(比如0.5-2秒),而不是只在批次结束后休眠。这样能避免瞬间发送大量请求触发反爬,同时比大批次长休眠的效率更高。

  • 引入代理IP池
    403错误大多是IP被Glassdoor限制了,用稳定的高匿代理IP池轮询每个请求的IP,能大幅降低被封禁的概率。每次请求随机从池中选一个代理,注意定期清理失效代理,保证请求成功率。

  • 优化请求头模拟真实浏览器
    检查你的DEFAULT_HEADERS,不要固定单一的User-Agent,维护一个常见浏览器的User-Agent列表,每次请求随机选取;同时补充Accept-Language、Referer、Cache-Control等字段,让请求更贴近真实用户行为。

  • 改用异步框架+精准限速
    替换grequests为aiohttp,搭配aiometer这类限速库,能更精细地控制并发数和请求频率。比如设置每秒最多发送5个请求,并发数不超过10,流量更平稳,不容易触发反爬。示例代码思路:

    import aiohttp
    import asyncio
    from aiometer import run_on_each
    from random import choice
    
    USER_AGENTS = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 13_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15",
        # 更多UA
    ]
    
    async def fetch_page(session, url):
        headers = {
            "User-Agent": choice(USER_AGENTS),
            "Accept-Language": "en-US,en;q=0.9",
            "Referer": "https://www.glassdoor.com/"
        }
        async with session.get(url, headers=headers) as response:
            if response.status == 200:
                return await response.text()
            # 处理403等错误,比如重试或切换代理
            return None
    
    async def main():
        # 生成所有需要爬取的评论页面URL列表
        urls = [reviews_url.replace(".htm", f"_P{page_num}.htm") for page_num in range(1, num_pages+1)]
        async with aiohttp.ClientSession() as session:
            # 限制每秒最多5个请求,同时最多10个请求并发
            results = await run_on_each(
                urls,
                lambda url: fetch_page(session, url),
                max_at_once=10,
                max_per_second=5
            )
        # 处理爬取结果
        print(f"成功获取{len([r for r in results if r])}页数据")
    
    if __name__ == "__main__":
        asyncio.run(main())
    
  • 尝试抓取内部API接口
    打开浏览器开发者工具,查看加载评论时的网络请求,很多时候Glassdoor会通过XHR请求加载评论数据(JSON格式),直接调用这些API接口比爬取HTML页面效率高得多,反爬限制也可能更宽松。

  • 分时段错峰爬取
    避开工作日白天的访问高峰,选择凌晨、深夜等时段爬取,此时网站的反爬检测会相对宽松,可适当提高请求速率,减少等待时间。


内容的提问来源于stack exchange,提问作者Dunc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:10:38