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 / JavaScript
https://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$env:PROXY_USER="替换为控制台代理用户名"
$env: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。