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

Scrapy-playwright爬虫response.meta缺失page/playwright_page问题求助

解决Scrapy-Playwright无法获取Page对象的问题及替代方案

从运行日志的Enabled downloader middlewares部分可以看到:Scrapy并未加载scrapy_playwright.middleware.PlaywrightMiddleware,请求仍由默认下载器处理,因此response.meta中不会包含Playwright的Page对象。下面给出两种解决方案:


修复现有Scrapy-Playwright代码

1. 补充核心配置项

在Spider的custom_settings中添加DOWNLOAD_HANDLERS,替换默认的HTTP/HTTPS下载器为Playwright实现,确保请求由Playwright处理:

custom_settings = {
    'CONCURRENT_REQUESTS': 1,
    'DOWNLOAD_DELAY': 3,
    'COOKIES_ENABLED': False,
    'PLAYWRIGHT_BROWSER_TYPE': 'chromium',
    # 新增:替换默认下载器
    'DOWNLOAD_HANDLERS': {
        "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
        "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
    },
    'MIDDLEWARES': {
        'scrapy_playwright.middleware.PlaywrightMiddleware': 800,
    },
}

2. 确保Playwright浏览器已安装

执行命令安装Chromium:

playwright install chromium

3. 修正CrawlerProcess初始化(可选)

如果自定义设置仍不生效,可将Spider配置直接传入CrawlerProcess:

def main(domain, stop, user_agent):
    settings = GoogleSpider.custom_settings.copy()
    settings['USER_AGENT'] = user_agent
    process = CrawlerProcess(settings=settings)
    process.crawl(GoogleSpider, domain=domain, stop=stop)
    process.start()

4. 处理异步兼容性

在执行文件开头添加代码,确保Scrapy使用支持异步的Reactor:

import asyncio
from twisted.internet.asyncioreactor import AsyncioSelectorReactor
AsyncioSelectorReactor(asyncio.get_event_loop())

纯Playwright替代方案(更简洁易调试)

如果不想依赖Scrapy,直接用Playwright编写独立脚本,逻辑与原代码一致,且无需处理Scrapy的配置与中间件问题:

from playwright.async_api import async_playwright
import asyncio

async def crawl_google(domain, stop_count, user_agent):
    search_url = f'https://www.google.com/search?q=intitle%3A%28%22Data+Scientist%22+OR+%22Data+Engineer%22+OR+%22Machine+Learning%22+OR+%22Data+Analyst%22+OR+%22Software+Engineer%22%29+Remote+-%22Director%22+-%22Principal%22+-%22Staff%22+-%22Frontend%22+-%22Front+End%22+-%22Full+Stack%22+site%3A{domain}%2F%2A+after%3A2023-03-27'
    
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(user_agent=user_agent)
        page = await context.new_page()
        
        await page.goto(search_url, wait_until='networkidle')
        
        collected_urls = []
        current_length = 0
        
        while len(collected_urls) < stop_count:
            # 提取搜索结果链接
            urls = await page.locator('.yuRUbf>a').evaluate_all('nodes => nodes.map(n => n.href)')
            # 过滤目标域名且未收集的链接
            new_urls = [url for url in urls if domain in url and url not in collected_urls]
            collected_urls.extend(new_urls)
            
            # 达到停止数量则截断
            if len(collected_urls) >= stop_count:
                collected_urls = collected_urls[:stop_count]
                break
            
            # 滚动加载更多
            if len(urls) > current_length:
                current_length = len(urls)
                await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
                await page.wait_for_timeout(1500)
                await page.wait_for_selector('.yuRUbf>a', state='visible')
            else:
                # 无更多结果,退出循环
                break
        
        # 输出结果
        print(f'收集到 {len(collected_urls)} 个URL:')
        for url in collected_urls:
            print(url)
        
        await browser.close()

if __name__ == '__main__':
    domain = 'jobs.lever.co'
    stop = 25
    user_agent3 = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.2; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)"
    asyncio.run(crawl_google(domain, stop, user_agent3))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 11:54:52