PYTHON BROWSER AUTOMATION

Python Playwright代理采集

Playwright在浏览器启动时设置123Proxy网关和账密,等待页面网络稳定后读取渲染完成的DOM,连续采集3页并写入JSON。

语言Python 3.10+框架Playwright测试目标Quotes to Scrape / JavaScript输出quotes-playwright.json
打开对应产品提取 查看测试目标
01
END-TO-END RESULT

采集JavaScript渲染页面并翻页

测试目标Quotes to Scrape / JavaScripthttps://quotes.toscrape.com/js/ 运行时Python 3.10+Playwright 输出文件结构化数据quotes-playwright.json

代码直接连接隧道代理固定网关 proxy.123proxy.cn:36923。主机与端口无需替换,出口路由由当前产品配置决定;你只需设置控制台生成的完整代理用户名和密码。

02
CREDENTIALS

只把代理账密放进环境变量

PROXY_USER必须是控制台中的代理用户名,不是网站登录手机号。地区和SESSION场景应复制控制台生成的完整路由用户名。

export PROXY_USER="替换为控制台代理用户名"
export PROXY_PASS="替换为控制台代理密码"
# 隧道代理固定网关:proxy.123proxy.cn:36923

不要把真实代理密码提交到Git仓库、镜像、日志或前端代码中。

03
COMPLETE PROGRAM

scrape_js.py

以下代码包含完整入口和输出逻辑。安装注释、运行命令与依赖声明保留在文件顶部,复制为对应文件后即可执行。

# requirements:
#   python -m pip install playwright
#   playwright install chromium
import asyncio
import json
import os
from urllib.parse import urljoin

from playwright.async_api import async_playwright

PROXY_HOST = "proxy.123proxy.cn"
PROXY_PORT = 36923
PROXY_USER = os.environ["PROXY_USER"]
PROXY_PASS = os.environ["PROXY_PASS"]
START_URL = "https://quotes.toscrape.com/js/"
MAX_PAGES = 3


async def main():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch(
            headless=True,
            proxy={
                "server": f"http://{PROXY_HOST}:{PROXY_PORT}",
                "username": PROXY_USER,
                "password": PROXY_PASS,
            },
        )
        context = await browser.new_context(
            user_agent="123Proxy-Developer-Example/1.0",
            locale="en-US",
        )
        page = await context.new_page()
        page.set_default_navigation_timeout(45_000)

        records = []
        url = START_URL
        for _ in range(MAX_PAGES):
            await page.goto(url, wait_until="networkidle")
            await page.locator("div.quote").first.wait_for()

            records.extend(
                await page.locator("div.quote").evaluate_all(
                    """nodes => nodes.map(node => ({
                      text: node.querySelector("span.text")?.textContent.trim(),
                      author: node.querySelector("small.author")?.textContent.trim(),
                      tags: [...node.querySelectorAll("a.tag")]
                        .map(tag => tag.textContent.trim()),
                      source_url: location.href
                    }))"""
                )
            )

            next_link = page.locator("li.next > a")
            if await next_link.count() == 0:
                break
            href = await next_link.get_attribute("href")
            url = urljoin(page.url, href)

        with open("quotes-playwright.json", "w", encoding="utf-8") as output:
            json.dump(records, output, ensure_ascii=False, indent=2)

        print(
            f"saved {len(records)} records to quotes-playwright.json"
        )
        await context.close()
        await browser.close()


if __name__ == "__main__":
    asyncio.run(main())
04
ENGINEERING CHECKS

案例没有省略的关键逻辑

01代理在chromium.launch阶段设置,覆盖页面资源请求
02用户名与密码使用独立字段,不拼进server
03等待networkidle及目标元素,避免固定长时间sleep
04复用同一BrowserContext完成连续分页
05
SWITCH PROXY PRODUCT

替换网关,不改采集逻辑

代理产品网关域名端口适合任务
隧道代理proxy.123proxy.cn36923混合池 / 纯住宅池
隧道住宅代理residential.123proxy.cn33000国家地区与SESSION
不限量动态住宅unlimit.residential.123proxy.cn10253不限流量住宅任务
两类静态代理控制台分配的固定代理IP返回端口直连IP,无网关域名
隧道住宅代理的国家与SESSION写在完整代理用户名中

网关固定为 residential.123proxy.cn:33000。例如使用美国SESSION时,直接把控制台生成的完整用户名作为 PROXY_USER,代码无需解析或重组。

06
PRIMARY REFERENCES

框架文档与测试目标

07
TROUBLESHOOTING

常见问题

为什么浏览器采集比Requests消耗更多并发?

浏览器会同时加载HTML、JavaScript、CSS、字体、图片和接口,一个页面通常产生多条并发请求。

什么时候适合使用不限量动态住宅?

持续浏览器任务需要较多流量和并发时可考虑不限量动态住宅,并使用固定网关unlimit.residential.123proxy.cn:10253。

SESSION应该如何保持?

使用隧道住宅或隧道代理纯住宅池时,把控制台生成的完整SESSION用户名作为PROXY_USER,并复用同一BrowserContext。