Python爬虫进阶:Playwright请求拦截(Request Interception)与动态代理IP实战

爬虫代理

前言

大家好,在日常的爬虫开发和自动化抓取中,我们经常会遇到一些让人头疼的场景。比如目标网站加载了大量无关的图片和视频拖慢了抓取速度,或者通过检测请求头和前端特征来封禁我们的机器。今天,我们就来深入探讨一下 Playwright 的一项高级杀手锏——请求拦截(Request Interception),并结合爬虫代理,实现高效、高并发、防屏蔽的工业级爬虫。

一、 为什么我们需要请求拦截?

在实际的爬虫抓取场景中,我们经常会面临以下痛点:

* 资源浪费:目标网站请求了额外的静态资源(如图片、CSS、大字体文件),严重拖慢了页面加载速度,浪费了宝贵的带宽。

* 认证与状态管理:登录态 token 藏在请求头里,需要在每次请求发送前动态注入。

* 代理动态切换:使用代理 IP 抓取时,需要考虑代理认证信息如何正确附加,以及如何强制隧道代理切换 IP。

* 绕过前端反爬:前端包含大量探针(如 navigator.webdriver),如果不在请求层面或加载前拦截,极易被识别。

这些问题的核心诉求就是:在请求发出去之前或响应回来之前,能够拦截并修改它。

二、 Playwright 请求拦截的核心机制

Playwright 实现请求拦截主要依赖两个核心对象:

* RouteRoute 对象:代表一个待处理的请求,它赋予了我们控制请求后续走向的权力,常见的方法有放行 continue()、伪造响应 fulfill() 以及直接中断 abort()。

* RequestRequest 对象:代表已发出或正在发出的请求,我们可以从中读取关键的上下文信息,例如通过 url()、headers()、method() 获取请求详情。

当页面触发网络请求时,只要我们通过 page.route(url, handler) 注册了对应 URL 模式的拦截器,Playwright 就会把 Route 对象交给我们处理。请注意,在处理函数中,必须调用 continue()、fulfill() 或 abort() 三者之一来结束拦截,否则请求会一直挂起continue()fulfill()abort()。

三、 实战:结合爬虫代理实现请求拦截与特征抹除

下面是一套综合实战代码。我们将演示如何配置全局隧道代理、如何通过拦截器丢弃无用静态资源、如何动态切换代理 IP,以及如何抹除自动化工具特征。

import asyncio

import uuid

import os

from playwright.async_api import async_playwright, Route, Request

# 亿牛云爬虫代理配置信息 (请替换为您自己的专属信息)

PROXY_HOST = "代理服务器"

PROXY_PORT = "31111"

PROXY_USER = "your_username"

PROXY_PASS = "your_password"

async def mock_static_handler(route: Route, request: Request):

    """

    静态资源拦截器:提高页面加载速度

    """

    url = request.url.lower()

    # 拦截图片资源并中止请求,极大提升抓取效率

    if url.endswith(".png") or url.endswith(".jpg"):

        await route.abort() #

    # 字体文件直接跳过,减少加载时间

    elif url.endswith(".woff2"):

        await route.abort() #

    else:

        # 非目标请求,继续正常流程

        await route.continue_() #

async def controlled_ip_handler(route: Route, request: Request):

    """

    代理 IP 动态切换拦截器:通过附加 Proxy-Tunnel 头部实现

    """

    # 每次请求生成新的 UUID 作为 tunnel 值,触发亿牛云强制分配新出口 IP

    tunnel_id = str(uuid.uuid4()) #


    # 动态注入自定义请求头,并将原请求头合并

    await route.continue_(headers={

        **request.headers,

        "Proxy-Tunnel": tunnel_id, #

        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" #

    })

async def main():

    async with async_playwright() as p:

        # 1. 启动浏览器并配置全局代理

        # 注意:proxy.server 格式必须是 http,Playwright不支持https前缀的代理

        browser = await p.chromium.launch(

            headless=True,

            proxy={

                "server": f"http://{PROXY_HOST}:{PROXY_PORT}", #

                "username": PROXY_USER, #

                "password": PROXY_PASS, #

            }

        )


        # 忽略HTTPS证书错误,这在国内服务器代理环境中非常实用

        context = await browser.new_context(ignore_https_errors=True) #

        page = await context.new_page()

        # 2. 全局注入:页面加载前执行,清除 webdriver 标识,绕过常规反爬

        await context.add_init_script("""

            Object.defineProperty(navigator, 'webdriver', {get: () => undefined});

            window.webdriver = undefined;

            delete window.CallSelenium;

        """) #

        # 3. 注册请求拦截器

        # 注意:page.route() 注册的拦截器按顺序匹配,第一个匹配的拦截器处理后,后续不再调用


        # 拦截所有API请求,实现动态代理IP切换

        await page.route("**/api/**", controlled_ip_handler)


        # 拦截所有其他请求,过滤无用静态资源

        await page.route("**/*", mock_static_handler)

        try:

            # 4. 执行抓取动作 (以httpbin为例验证IP和Header)

            print("正在访问目标网站...")

            await page.goto("IP查询网站")


            # 等待网络空闲

            await page.wait_for_load_state("networkidle") #


            content = await page.content()

            print("抓取成功,页面返回的IP信息:", content[:500])


        except Exception as e:

            print(f"抓取发生异常: {e}")

        finally:

            await browser.close()

if __name__ == "__main__":

    asyncio.run(main())

四、 避坑与注意事项

在实际开发中,关于 Request Interception 有几个关键细节需要大家注意:

1. 拦截器的链式冲突:上面代码提到了,Playwright 的拦截器是匹配即止的。如果你的一个请求同时命中了静态资源匹配和 API 匹配,只有先注册/先命中的会被执行。如果需要链式处理,建议在一个 handler 里整合逻辑。

2. 异常捕获:如果拦截器抛出异常且未被捕获,Playwright 会默认放行该请求。在工业级爬虫里,建议给 Handler 加上 try/except,异常时主动 await route.abort("failed") 防止真实 IP 或特征泄露。

3. 代理排查:如果抓取时发现 IP 还是本机,或者报错连不上,快速检查下配置格式是否带有 http:// 前缀,或者直接用 curl  测试一下代理服务的连通性。

总结

掌握 Playwright 的请求拦截,就像是给爬虫装上了“透视眼”和“手术刀”。结合高质量的代理IP,我们不仅能在网络层做到无缝伪装,还能大幅优化抓取性能,降低带宽成本。

如果你在爬虫架构设计或 Playwright 部署上有什么问题,欢迎在评论区留言交流。我们下期技术干货再见!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容