Playwright是由微软公司2020年初发布的新一代自动化测试工具,相较于目前最常用的Selenium,它仅用一个API即可自动执行Chromium、Firefox、WebKit等主流浏览器自动化操作。

对各种开发语言也有非常好的支持。常用的NodeJs、Java、python都有支持,且有丰富的文档参考。

Python环境下的安装使用

1、安装依赖库

pip install playwright

2、安装浏览器驱动文件

安装好依赖库之后,会自动注册全局命令。下面2种方式都可以快速安装驱动文件(驱动就是内置的浏览器)

python -m playwright install

或者:

playwright install

如果命令是python3,替换为pip3 install 和python3 -m 即可。

网上有非常多的教程。安装并非本文的重点。

多环境隔离的应用场景

常见的如爬虫,可能需要使用代理IP隔离开不同的浏览器进行数据抓取。

像另一些需要多号操作的营销内容,也需要多个浏览器互相隔离开。更高要求的才会使用代理+隔离的方式。

产生完全不一样的浏览器环境。比如大量的号去做不同的事。

还有很多常用的场景。独立干净的浏览器环境+Playwright的自动化。可以实现非常多的有趣的应用。

Playwright启动浏览器有几种模式。我们需要先进行了解。

1、普通的无痕模式,用完即销毁。这种方式下,浏览器的历史记录之类的不会保存。适合用于爬虫性的工作。

代码大致是这样的。

browser = pw.chromium.launch(headless=headless, proxy=my_proxy,
ignore_default_args=ignore_args,
args=default_args) browserContext = browser.new_context(user_agent=userAgent, storage_state=storage_state)

可以指定UserAgent,这是我们模拟不同操作系统和浏览器数据的必填项。

也可以指定headless无头模式,这样浏览器不会有界面出现。背后去工作。

2、普通的持久模式,需要指定用户的数据目录。实现数据的隔离。

比如1号浏览器存到data1,2号存到data2,数据不会冲突,各干各的事,可以同时登陆一个网站的多个账号,互不影响。

不方便的地方在于,每次执行完任务,浏览器会随着程序关闭而关闭。

copy一段网上的示例

# 获取 google chrome 的本地缓存文件
USER_DIR_PATH = f"C:\\Users\\{getpass.getuser()}\\AppData\Local\Google\Chrome\\User Data" with sync_playwright() as p:
browser = p.chromium.launch_persistent_context(
# 指定本机用户缓存地址,这是隔离环境的主要点,指定不同的目录存放用户的数据。
user_data_dir=USER_DIR_PATH,
# 接收下载事件,允许下载需要
accept_downloads=True,
# 设置 GUI 模式,可以看到浏览器界面
headless=False,
bypass_csp=True,
slow_mo=1000,
channel="chrome",
) page = browser.new_page()
page.goto("https://www.cnblogs.com/yoyoketang") page.pause()

3、直连系统的Chrome。如果系统有Chrome浏览器,playwright可以直接连接,并进行操作。但是需要做一些配置。

这也是我目前用得最多的模式。

核心的原理就是使用CDP连接上Chrome。需要开启Chrome时,指定一个调试端口,供我们远程连接上去使用。

官方提供的具体函数是

pw.chromium.connect_over_cdp(cdp_url, timeout=0)

优点在于:

脚本和浏览器分离。脚本开不开,浏览器都不影响。只是需要自动化的时候,脚本才去工作。

缺点:

就是配置略麻烦。好在封装好之后,就是一次的麻烦,后面也会比较顺畅。

如何封装属于自己的快速启动类,python和java都可以,下次再聊。

下面以Chrome浏览器+动态代理为例构建多个不同的环境

由于Chrome自带的proxy 代理功能并不支持带账号密码的代理方式。

而我们采购的代理,肯定都是有账号密码的。

所以核心点是添加一个插件,配置上代理,能支持http和socks5的代理,并支持账号密码进行连接。

然后再通过python,调用系统的浏览器,产生不同的环境,使用不同的代理IP。就能达到目标。

直接上图

没有好用的收费代理,本地模拟了一个HK节点的代理。

可以看到4个浏览器的指纹已经不一样了。配合上代理,就是干净的环境了。

核心的逻辑在于启用不同的DataDir用户数据目录,加个独立的代理插件来支持http和socks5的代理,

1、核心1,使用python来快速启动Chrome

if sys.platform.startswith('linux'):  # Linux
exe_name = 'chrome'
extParam.append('--no-sandbox')
elif sys.platform.startswith('win'): # Windows
win_path = 'C:\Program Files\Google\Chrome\Application\chrome.exe'
exe_name = win_path if os.path.exists(win_path) else 'chrome.exe'
elif sys.platform.startswith('darwin'): # Mac
exe_name = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
extParam.append('--no-sandbox') # 启用UA
if config.get('user_agent'):
extParam.append(fr'--user-agent="{config.get("user_agent")}"') # 启用无痕
if config.get('incognito'):
extParam.append('--incognito') # 无开屏
if config.get('no_window'):
extParam.append('--no-startup-window') command = fr'"{exe_name}" --remote-debugging-port={port} --user-data-dir="{data_dir}" --no-sandbox --disable-gpu --disable-software-rasterize --disable-background-networking --disable-background-mode --disable-sync --disable-blink-features=AutomationControlled --disable-client-side-phishing-detection --disable-default-apps --disable-desktop-notifications --disable-hang-monitor --disable-infobars --disable-notifications --disable-plugins-discovery --no-first-run --dns-prefetch-disable --ignore-certificate-errors --allow-running-insecure-content --test-type --origin-trial-disabled-features=WebGPU --no-default-browser-check --no-service-autorun --disable-popup-blocking --password-store=basic --disable-web-security --disable-dev-shm-usage --disable-component-update --disable-features=RendererCodeIntegrity --disable-features=FlashDeprecationWarning,EnablePasswordsAccountStorage {" ".join(extParam)}' os.popen(command)

还有不少代码,就不往上面贴了。

2、核心点2,动态加载插件进不同的Chrome环境,各用各的代理。

def create_proxyauth_extension(proxy_host, proxy_port,
proxy_username, proxy_password,
scheme='http', plugin_dir=None):
"""
代理认证插件,返回代理插件的地址
Chrome使用带账号密码的代理IP
插件来源:https://github.com/henices/Chrome-proxy-helper
参考:https://ask.hellobi.com/blog/cuiqingcai/10307#articleHeader5
https://my.oschina.net/sunboy2050/blog/1858508
https://github.com/aneasystone/selenium-test/blob/master/08-proxy-with-password.py
https://developer.chrome.com/extensions/proxy
args:
proxy_host (str): 你的代理地址或者域名(str类型)
proxy_port (int): 代理端口号(int类型)
proxy_username (str):用户名(字符串)
proxy_password (str): 密码 (字符串)
kwargs:
scheme (str): 代理方式 默认http
plugin_dir (str): 扩展的目录路径 return str -> plugin_path
""" # 插件目录
if not plugin_dir:
plugin_dir = os.path.join(get_data_dir('chrome_plugin'), f'custom_proxyauth_plugin')
if not os.path.exists(plugin_dir):
os.makedirs(plugin_dir) # 生成的Zip文件地址
plugin_file = os.path.join(plugin_dir, f"proxy_plugin_{proxy_host}_{proxy_port}.zip")
# 旧文件清理掉
if os.path.exists(plugin_file):
os.remove(plugin_file) manifest_json = """
{
"version": "1.0.0",
"manifest_version": 2,
"name": "Chrome Proxy",
"permissions": [
"proxy",
"tabs",
"unlimitedStorage",
"storage",
"<all_urls>",
"webRequest",
"webRequestBlocking"
],
"background": {
"scripts": ["background.js"]
},
"minimum_chrome_version":"22.0.0"
}
""" background_js = string.Template(
"""
var config = {
mode: "fixed_servers",
pacScript: {},
rules: {
singleProxy: {
scheme: "${scheme}",
host: "${host}",
port: ${port}
},
bypassList: ["foobar.com"]
}
}; chrome.proxy.settings.set({value: config, scope: "regular"}, function() {}); function callbackFn(details) {
return {
authCredentials: {
username: "${username}",
password: "${password}"
}
};
} chrome.webRequest.onAuthRequired.addListener(
callbackFn,
{urls: ["<all_urls>"]},
['blocking']
);
"""
).substitute(
host=proxy_host,
port=proxy_port,
username=proxy_username,
password=proxy_password,
scheme=scheme,
) # 先写ZIP
with zipfile.ZipFile(plugin_file, 'w') as zp:
zp.writestr("manifest.json", manifest_json)
zp.writestr("background.js", background_js) # 再手写文件过去
with open(os.path.join(plugin_dir, 'manifest.json'), 'w+') as fi:
fi.write(manifest_json) with open(os.path.join(plugin_dir, 'background.js'), 'w+') as fi:
fi.write(background_js) return plugin_file

Java也可以用同样的方式实现。后续配上Java的多线程。相信开100个窗口干活,不是什么难事。

Playwright在下载上传方面,比以前的Selenium要强很多。还有很多功能,下次再分享。

关注我的公众号:青塬科技,定期分享经验文章。

【自动化】使用PlayWright+代理IP实现多环境隔离的更多相关文章

  1. 使用TaskManager爬取2万条代理IP实现自动投票功能

    话说某天心血来潮想到一个问题,朋友圈里面经常有人发投票链接,让帮忙给XX投票,以前呢会很自觉打开链接帮忙投一票.可是这种事做多了就会考虑能不能使用工具来进行投票呢,身为一名程序猿决定研究解决这个问题. ...

  2. 爬虫平台设置代理ip

    首先从国外一个网站爬取了免费的代理ip信息存到mongodb中:接着代码设置: 在爬虫客户端抽象类中添加属性: 设置代理的代码其实就以下几句: firefoxProfile.setPreference ...

  3. UA池 代理IP池 scrapy的下载中间件

    # 一些概念 - 在scrapy中如何给所有的请求对象尽可能多的设置不一样的请求载体身份标识 - UA池,process_request(request) - 在scrapy中如何给发生异常的请求设置 ...

  4. python爬虫成长之路(二):抓取代理IP并多线程验证

    上回说到,突破反爬虫限制的方法之一就是多用几个代理IP,但前提是我们得拥有有效的代理IP,下面我们来介绍抓取代理IP并多线程快速验证其有效性的过程. 一.抓取代理IP 提供免费代理IP的网站还挺多的, ...

  5. Wireshark抓包分析/TCP/Http/Https及代理IP的识别

    前言 坦白讲,没想好怎样的开头.辗转三年过去了.一切已经变化了许多,一切似乎从没有改变. 前段时间调研了一次代理相关的知识,简单整理一下分享之.如有错误,欢迎指正. 涉及 Proxy IP应用 原理/ ...

  6. python爬虫实战(一)——实时获取代理ip

    在爬虫学习的过程中,维护一个自己的代理池是非常重要的. 详情看代码: 1.运行环境 python3.x,需求库:bs4,requests 2.实时抓取西刺-国内高匿代理中前3页的代理ip(可根据需求自 ...

  7. python使用代理ip发送http请求

    一.需求背景 网站刷票时,经常会遇到限制一个ip只能投票一次的限制,为此需要使用代理ip 二.脚本如下: 1.Proxy_http.py使用代理ip发送httpr的get和post请求 #coding ...

  8. 【原创】验证代理IP是否有用

    /// <summary> /// 验证代理IP是否有用 /// </summary> /// <param name="ip">IP地址< ...

  9. [python]爬代理ip v2.0(未完待续)

    爬代理ip 所有的代码都放到了我的github上面, HTTP代理常识 HTTP代理按匿名度可分为透明代理.匿名代理和高度匿名代理. 特别感谢:勤奋的小孩 在评论中指出我文章中的错误. REMOTE_ ...

  10. 通过爬虫代理IP快速增加博客阅读量——亲测CSDN有效!

    写在前面 题目所说的并不是目的,主要是为了更详细的了解网站的反爬机制,如果真的想要提高博客的阅读量,优质的内容必不可少. 了解网站的反爬机制 一般网站从以下几个方面反爬虫: 1. 通过Headers反 ...

随机推荐

  1. 原生js判断某个区域的滚动条滚动到了底部

    原生js判断某个区域的滚动条滚动到了底部### 讲解==> 关系公式:element.scrollHeight - element.scrollTop === element.clientHei ...

  2. 【JS 逆向百例】X球投资者社区 cookie 参数 acw_sc__v2 加密分析

    关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...

  3. 使用Lua做为MMOARPG游戏逻辑开发脚本的一点体会

    项目背景 目前在一个大型MMOARPG游戏中使用Lua做为逻辑开发语言,Lua占整体代码量的80%. 我们这个MMO游戏开发近2年,客户端8人,项目组总体人数在100人(美术占70%),目前代码量很大 ...

  4. Windows10磁盘占用100%和内存占用高

    前言 公司配备了两台电脑,两台电脑都是安装的win10系统,一台是磁盘占用高,另一台是内存可用低. 具体情况如下: 一台外网机 8g内存,安装win10 专业版,开机一天后经常出现内存不够用,但其实都 ...

  5. go中channel源码剖析

    channel 前言 设计的原理 共享内存 csp channel channel的定义 源码剖析 环形队列 创建 写入数据 读取数据 channel的关闭 优雅的关闭 M个receivers,一个s ...

  6. silce的扩容,截取,使用规范总结

    切片 什么是slice slice的创建使用 slice使用的一点规范 slice和数组的区别 slice的append是如何发生的 复制Slice和Map注意事项 接收 Slice 和 Map 作为 ...

  7. python处理Excel实现自动化办公教学(含实战)【二】

    相关文章: python处理Excel实现自动化办公教学(含实战)[一] python处理Excel实现自动化办公教学(含实战)[二] python处理Excel实现自动化办公教学(数据筛选.公式操作 ...

  8. C/C++ 常用开发代码片段

    由于内容较少,所以,不想把它放在我的本地博客中了,暂时保存在这里,代码有一部分来源于网络,比较经典的案例,同样收藏起来. Stack 栈容器 Stack容器适配器中的数据是以LIFO的方式组织的,它是 ...

  9. C/C++ Qt 命令行版网络通信

    通常情况下Qt如果需要建立网络通信则必须依附于图形界面,但如果是新手入门,图形界面则显得太过于繁琐不利于学习原理,如下本人实现了命令行版本的网络通信案例,能够让读者更好的理解Qt是如何创建网络通信套接 ...

  10. 从嘉手札<2023-12-15>

    荒原  朔方 2023.12.15 人生实属是很愁的时间 愁到听不见一点雪花飘落的声音 愁到连随便写点文章都算得上拼尽全力 萧瑟的北风吹散了为数不多的倔强 漫天的雪花飞舞 埋葬的是那么多年走过的春秋 ...