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

使用Pyppeteer抓取Digikala商品页面时返回None或空内容的问题求助

使用Pyppeteer抓取Digikala商品页面时返回None或空内容的问题求助

我完全理解你遇到的这种 frustration——动态渲染的电商页面反爬机制通常很严格,Pyppeteer 看似配置正确但就是拿不到内容的情况确实很头疼。结合你的代码和尝试过的方法,我来帮你一步步排查和解决问题:

1. 核心问题:Digikala 检测到了 Pyppeteer 的自动化特征

Digikala 这类电商平台会通过多种方式识别爬虫,比如检测 window.navigator.webdriver 标志、无头浏览器特征、异常的请求头或浏览器启动参数。你的当前代码没有做任何反检测处理,大概率是被识别为爬虫,直接返回了空内容或者触发了超时。

解决办法:隐藏自动化特征 + 模拟真实浏览器

修改你的 launch 参数和页面配置,添加反检测的关键设置:

a. 调整浏览器启动参数

在 launch 中添加以下 args,绕过常见的自动化检测:

browser = await launch(
    executablePath=self.chromium_path,
    headless=True,  # 可以先临时设为 False,手动观察页面是否加载正常
    args=[
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-blink-features=AutomationControlled',  # 禁用自动化控制检测
        '--disable-dev-shm-usage',  # 解决内存不足问题
        '--start-maximized',  # 模拟窗口最大化
    ]
)

b. 清除 webdriver 标志

在创建页面后,通过 JS 覆盖 navigator.webdriver 属性,避免被检测:

page = await browser.newPage()
# 添加这一段代码隐藏自动化特征
await page.evaluate('''() => {
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    })
}''')

c. 配置真实的请求头

确保你设置了完整的请求头,至少包含和真实浏览器一致的 User-Agent:

# 可以从你自己的浏览器开发者工具中复制真实的 User-Agent
default_headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    'Referer': 'https://www.digikala.com/'
}
if headers:
    default_headers.update(headers)
await page.setExtraHTTPHeaders(default_headers)

2. 优化页面等待逻辑:避免依赖固定 sleep

你的代码里用了 await asyncio.sleep(2),这其实不可靠——页面渲染时间可能因网络波动或反爬机制变长。换成等待关键元素加载完成的方式更稳妥:

# 替换 await asyncio.sleep(2)
try:
    # 等待商品页的核心元素加载(比如你要抓取的标题容器)
    await page.waitForSelector('h1.text-h5-180', timeout=30000)
except TimeoutError:
    print("关键元素加载超时,可能触发反爬")
    return None

3. 完善错误排查:捕获所有异常并输出详情

你的当前代码只捕获了 TimeoutError,但可能还有其他错误(比如浏览器启动失败、页面加载被中断)导致 content 为 None。扩大异常捕获范围,打印具体错误信息:

except TimeoutError:
    print(f'Timeout while loading {url} or waiting for elements')
    return None
except Exception as e:
    print(f"发生未知错误:{str(e)}")
    return None

4. 验证 Chromium/Chrome 兼容性

你指定的是 Chrome 而非 Chromium 路径,虽然两者核心一致,但 Pyppeteer 对 Chromium 的兼容性更好。如果问题仍存在,可以尝试:

  • 让 Pyppeteer 自动下载兼容版本的 Chromium(去掉 executablePath 参数,首次运行会自动下载)
  • 确认你的 Chrome 版本和 Pyppeteer 版本兼容(比如 Pyppeteer v2.0+ 支持 Chrome 115+)

修改后的完整 fetch_content 方法示例

async def fetch_content(self, url, headers=None):
    # 默认请求头,可被传入的 headers 覆盖
    default_headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
        'Accept-Language': 'en-US,en;q=0.5',
        'Referer': 'https://www.digikala.com/'
    }
    if headers:
        default_headers.update(headers)
    
    try:
        browser = await launch(
            executablePath=self.chromium_path,
            headless=True,  # 先设为 False 观察页面加载状态
            args=[
                '--no-sandbox',
                '--disable-setuid-sandbox',
                '--disable-blink-features=AutomationControlled',
                '--disable-dev-shm-usage',
                '--start-maximized'
            ]
        )
        page = await browser.newPage()
        
        # 隐藏 webdriver 标志
        await page.evaluate('''() => {
            Object.defineProperty(navigator, 'webdriver', {
                get: () => undefined
            })
        }''')
        
        await page.setExtraHTTPHeaders(default_headers)
        await page.goto(url, {'waitUntil': 'networkidle2', 'timeout': 60000})
        
        # 等待核心元素加载
        await page.waitForSelector('h1.text-h5-180', timeout=30000)
        
        content = await page.content()
        await browser.close()
        return content
    except TimeoutError:
        print(f'Timeout while loading {url} or waiting for elements')
        return None
    except Exception as e:
        print(f"Error fetching {url}: {str(e)}")
        return None

最后一步:手动验证页面状态

把 headless 设为 False,运行代码后观察弹出的 Chrome 窗口:

  • 页面是否正常加载?有没有跳转到人机验证页面?
  • 控制台有没有报错?有没有资源加载失败的提示?
    如果看到验证码,那说明 Digikala 触发了更严格的反爬,这时候可能需要添加代理 IP 或处理验证码逻辑,但大部分情况下,上面的修改已经能绕过基础检测。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 11:30:27