Playwright 远程调用

https://blog.csdn.net/qq_36991535/article/details/124781189

# 指定缓存目录

调用本地浏览器调试

user_data_dir = "chromium-1005/chrome-win/user data"

# 指定可执行文件路径

executable_path = "chromium-1005/chrome-win/chrome.exe"

browser = playwright.chromium.launch_persistent_context(

            user_data_dir=user_data_dir,

            executable_path=executable_path,

            accept_downloads=True,

            headless=True, # 控制无头或有头

            bypass_csp=True,

            slow_mo=10,

            args=['--disable-blink-features=AutomationControlled'],# 禁用正在自动化控制提示

        )

page = browser.new_page()

page.goto("https://www.baidu.com")

page.wait_for_load_state(state="networkidle") # 等待一段时间内再无其它请求,相当于等画面完全加载

 

 

 

控制已打开的浏览器

command = "chrome/chrome --remote-debugging-port=9001"

if self.headless:

# 以无头模式启动浏览器

    command = "chrome/chrome --remote-debugging-port=9001 --headless"

subprocess.Popen(command)

print("浏览器已启动!等待进程创建...")

proccess_pid = ""

while True:

    time.sleep(1)

    with os.popen(f"netstat -ano | findstr 9001") as r:

        text = r.read()

        if len(text) > 0:

            pid_info = text.split("\n")[0].split(" ")

            # 获取进程ID

            proccess_pid = pid_info[len(pid_info) - 1]

            break

playwright = sync_playwright().start()

browser = playwright.chromium.connect_over_cdp("http://localhost:9001")

page = browser.new_page()

page.goto("https://www.baidu.com")

page.wait_for_load_state(state="networkidle")

# 关闭进程

os.popen(f"taskkill /im {proccess_pid } /F")

 

监听网络资源请求

def on_response(self, response):

    if "https://fanyi.baidu.com/v2transapi" in response.url:

        result = response.json()

        print(result)

 

user_data_dir = "chromium-1005/chrome-win/user data"

executable_path = "chromium-1005/chrome-win/chrome.exe"

browser = playwright.chromium.launch_persistent_context(

    user_data_dir=user_data_dir,

    executable_path=executable_path,

    accept_downloads=True,

    headless=True,

    bypass_csp=True,

    slow_mo=10,

    args=['--disable-blink-features=AutomationControlled'],

    # 设置代理

    proxy=ProxySettings(server="http://xxx.xxx.xxx.xxx:xxxx"),

)

page = browser.new_page()

# 监听响应事件

page.on("response", self.on_response)

page.goto("https://fanyi.baidu.com/#zh/jp/你好")

page.wait_for_load_state(state="networkidle")

禁止某些资源加载

 
def on_response(self, response):
    if "https://fanyi.baidu.com/v2transapi" in response.url:
        result = response.json()
        print(result)
 
# 取消请求
def cancel_request(self, route, request):
    route.abort()
user_data_dir = "chromium-1005/chrome-win/user data"
executable_path = "chromium-1005/chrome-win/chrome.exe"
browser = playwright.chromium.launch_persistent_context(
    user_data_dir=user_data_dir,
    executable_path=executable_path,
    accept_downloads=True,
    headless=True,
    bypass_csp=True,
    slow_mo=10,
    args=['--disable-blink-features=AutomationControlled'],
    # 设置代理
    proxy=ProxySettings(server="http://xxx.xxx.xxx.xxx:xxxx"),
)
page = browser.new_page()
# 正则匹配监听图片和css的请求
page.route(re.compile(r"(\.png)|(\.jpg)|(\.css)"), self.cancel_request)
# 监听响应事件
page.on("response", self.on_response)
page.goto("https://fanyi.baidu.com/#zh/jp/你好")
page.wait_for_load_state(state="networkidle")
 
 

模拟手机端

# 定义手机型号, 可以通过浏览器的开发者查看
phone_name="iPhone 12 Pro Max"
playwright = sync_playwright().start()
phone_obj = playwright.devices[phone_name]
 self.browser = self.playwright.chromium.launch_persistent_context(
     **phone_obj,
     user_data_dir=user_dir,
     executable_path=brows_executable_path,
     accept_downloads=True,
     headless=headless,
     bypass_csp=True,
     slow_mo=10,
     args=['--disable-blink-features=AutomationControlled']
 )

等待某个资源请求出现或完成

page.goto("https://www.baidu.com")

# 当出现请求地址地址包含www.baidu.com且响应状态为200时等待结束

page.expect_response(lambda response: "www.baidu.com" in response.url and response.status == 200)

 
一、Playwright的安装其实就是一个python的一个类库而已,所以使用pip install playwright命令安装即可。

二、安装浏览器及其驱动安装Playwright后,可以使用playwright install命令,会自动安装chromium、firefox、webkit等三款浏览器以及对应的驱动包。当然这个过程比较漫长,因为安装包比较大,后面会讲如何控制本地浏览器爬虫,所以这一步也可以选择跳过。
另外,如果在公司使用代理的情况下,使用以上命令可能无法安装。这种情况下,可以选择使用脚手架npm install playwright --proxy=xxx.xxx.xxx.xx:xx 这种方式去变相的安装浏览器。亲测~安装完了之后, python也是可以直接使用的。
三、Playwright的使用首先,贴一下官网API的地址:https://playwright.dev/python/docs/intro。官网已经讲得特别清楚了,而且有很多的实例,这里我就以我遇到的实际问题跟大家进行一个分享。
调用本地浏览器调试这种方式的好处在于,你完全可以把浏览器放到你的项目下,这样在其他机器上可以很好的兼容,不用你额外去执行命令安装浏览器,修改代码中的路径。
# 指定缓存目录user_data_dir = "chromium-1005/chrome-win/user data"# 指定可执行文件路径executable_path = "chromium-1005/chrome-win/chrome.exe"browser = playwright.chromium.launch_persistent_context(            user_data_dir=user_data_dir,            executable_path=executable_path,            accept_downloads=True,            headless=True, # 控制无头或有头            bypass_csp=True,            slow_mo=10,            args=['--disable-blink-features=AutomationControlled'],# 禁用正在自动化控制提示        )page = browser.new_page()page.goto("https://www.baidu.com")page.wait_for_load_state(state="networkidle") # 等待一段时间内再无其它请求,相当于等画面完全加载12345678910111213141516控制已打开的浏览器这种方式主要是因为通过playwright打开的浏览器在执行完任务后会自动关闭,为了减少浏览器的开销,节省时间,可已选择使用命令打开浏览器配合远程调试模式进行处理。
command = "chrome/chrome --remote-debugging-port=9001"if self.headless:# 以无头模式启动浏览器    command = "chrome/chrome --remote-debugging-port=9001 --headless"subprocess.Popen(command)print("浏览器已启动!等待进程创建...")proccess_pid = ""while True:    time.sleep(1)    with os.popen(f"netstat -ano | findstr 9001") as r:        text = r.read()        if len(text) > 0:            pid_info = text.split("\n")[0].split(" ")            # 获取进程ID            proccess_pid = pid_info[len(pid_info) - 1]            breakplaywright = sync_playwright().start()browser = playwright.chromium.connect_over_cdp("http://localhost:9001")page = browser.new_page()page.goto("https://www.baidu.com")page.wait_for_load_state(state="networkidle")# 关闭进程os.popen(f"taskkill /im {proccess_pid } /F")
123456789101112131415161718192021222324这种方式其实已经很好了,但是存在一个问题,当已经有浏览器被开启时,命令打开浏览器会从缓存加载,不会监听到远程端口, 必须要关掉所有的浏览器之后,才能正常进行控制。 这个问题, 如果有谁有好的方法去解决,就是一个非常完美的方案。欢迎大家探讨!
监听网络资源请求这是一个我认为非常强大的功能,早在学selenium的时候,我曾经探讨过这个问题,使用selenium要实现这个东西,当时各种百度,最终有了处理方案,但始终还不是特别满意。但是playwright把这一点简化到了极致,让我不禁被为它折服。
def on_response(self, response):    if "https://fanyi.baidu.com/v2transapi" in response.url:        result = response.json()        print(result)
user_data_dir = "chromium-1005/chrome-win/user data"executable_path = "chromium-1005/chrome-win/chrome.exe"browser = playwright.chromium.launch_persistent_context(    user_data_dir=user_data_dir,    executable_path=executable_path,    accept_downloads=True,    headless=True,    bypass_csp=True,    slow_mo=10,    args=['--disable-blink-features=AutomationControlled'],    # 设置代理    proxy=ProxySettings(server="http://xxx.xxx.xxx.xxx:xxxx"),)page = browser.new_page()# 监听响应事件page.on("response", self.on_response)page.goto("https://fanyi.baidu.com/#zh/jp/你好")page.wait_for_load_state(state="networkidle")1234567891011121314151617181920212223
以上是我通过这玩意儿抓取百度翻译的简单代码。但是需要特别注意一点,在需要代理的情况下,使用无头浏览器必须设置代理,像这样proxy=ProxySettings(server="http://xxx.xxx.xxx.xxx:xxxx"),,否则你会看到以下错误:
chromium浏览器:

webkit浏览器
但firefox却没有发现问题,所以你也可以使用火狐浏览器去避免这一问题。
禁止某些资源加载很多情况下,我们在抓取的时候并不是所有的请求都需要,但是又不得不等待画面加载完成再进行抓取。那么这种时候,我们可以使用router事件过滤我们不需要的请求,比如图片和css样式。
def on_response(self, response):    if "https://fanyi.baidu.com/v2transapi" in response.url:        result = response.json()        print(result)
# 取消请求def cancel_request(self, route, request):    route.abort()user_data_dir = "chromium-1005/chrome-win/user data"executable_path = "chromium-1005/chrome-win/chrome.exe"browser = playwright.chromium.launch_persistent_context(    user_data_dir=user_data_dir,    executable_path=executable_path,    accept_downloads=True,    headless=True,    bypass_csp=True,    slow_mo=10,    args=['--disable-blink-features=AutomationControlled'],    # 设置代理    proxy=ProxySettings(server="http://xxx.xxx.xxx.xxx:xxxx"),)page = browser.new_page()# 正则匹配监听图片和css的请求page.route(re.compile(r"(\.png)|(\.jpg)|(\.css)"), self.cancel_request)# 监听响应事件page.on("response", self.on_response)page.goto("https://fanyi.baidu.com/#zh/jp/你好")page.wait_for_load_state(state="networkidle")
12345678910111213141516171819202122232425262728最终去掉js和图片的画面:

加上禁止资源处理前,需要12s左右,加上后缩短都3s左右,极大的提升了抓取的效率。另外,如果某些js明确不会影响我们要抓取的数据,也可以做进一步的优化。
模拟手机端很多情况下我们需要模拟手机端的访问,playwright也能轻易做到。
# 定义手机型号, 可以通过浏览器的开发者查看phone_name="iPhone 12 Pro Max"playwright = sync_playwright().start()phone_obj = playwright.devices[phone_name] self.browser = self.playwright.chromium.launch_persistent_context(     **phone_obj,     user_data_dir=user_dir,     executable_path=brows_executable_path,     accept_downloads=True,     headless=headless,     bypass_csp=True,     slow_mo=10,     args=['--disable-blink-features=AutomationControlled'] )1234567891011121314// 支持的手机型号列表Blackberry PlayBookBlackberry PlayBook landscapeBlackBerry Z30BlackBerry Z30 landscapeGalaxy Note 3Galaxy Note 3 landscapeGalaxy Note IIGalaxy Note II landscapeGalaxy S IIIGalaxy S III landscapeGalaxy S5Galaxy S5 landscapeGalaxy S8Galaxy S8 landscapeGalaxy S9+Galaxy S9+ landscapeGalaxy Tab S4Galaxy Tab S4 landscapeiPad (gen 6)iPad (gen 6) landscapeiPad (gen 7)iPad (gen 7) landscapeiPad MiniiPad Mini landscapeiPad Pro 11iPad Pro 11 landscapeiPhone 6iPhone 6 landscapeiPhone 6 PlusiPhone 6 Plus landscapeiPhone 7iPhone 7 landscapeiPhone 7 PlusiPhone 7 Plus landscapeiPhone 8iPhone 8 landscapeiPhone 8 PlusiPhone 8 Plus landscapeiPhone SEiPhone SE landscapeiPhone XiPhone X landscapeiPhone XRiPhone XR landscapeiPhone 11iPhone 11 landscapeiPhone 11 ProiPhone 11 Pro landscapeiPhone 11 Pro MaxiPhone 11 Pro Max landscapeiPhone 12iPhone 12 landscapeiPhone 12 ProiPhone 12 Pro landscapeiPhone 12 Pro MaxiPhone 12 Pro Max landscapeiPhone 12 MiniiPhone 12 Mini landscapeiPhone 13iPhone 13 landscapeiPhone 13 ProiPhone 13 Pro landscapeiPhone 13 Pro MaxiPhone 13 Pro Max landscapeiPhone 13 MiniiPhone 13 Mini landscapeJioPhone 2JioPhone 2 landscapeKindle Fire HDXKindle Fire HDX landscapeLG Optimus L70LG Optimus L70 landscapeMicrosoft Lumia 550Microsoft Lumia 550 landscapeMicrosoft Lumia 950Microsoft Lumia 950 landscapeNexus 10Nexus 10 landscapeNexus 4Nexus 4 landscapeNexus 5Nexus 5 landscapeNexus 5XNexus 5X landscapeNexus 6Nexus 6 landscapeNexus 6PNexus 6P landscapeNexus 7Nexus 7 landscapeNokia Lumia 520Nokia Lumia 520 landscapeNokia N9Nokia N9 landscapePixel 2Pixel 2 landscapePixel 2 XLPixel 2 XL landscapePixel 3Pixel 3 landscapePixel 4Pixel 4 landscapePixel 4a (5G)Pixel 4a (5G) landscapePixel 5Pixel 5 landscapeMoto G4Moto G4 landscapeDesktop Chrome HiDPIDesktop Edge HiDPIDesktop Firefox HiDPIDesktop SafariDesktop ChromeDesktop EdgeDesktop Firefox
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116等待某个资源请求出现或完成有时我们只需要等待某一个请求出现或者完成就可以达到我们的目的,这种情况下,没必要等页面完全加载,这时候可以使用以下监听事件:
page.expect_request(url_or_predicate, **kwargs) // 期待出现某个请求时page.expect_request_finished(url_or_predicate, **kwargs) // 期待某个请求完了时使用page.expect_response(url_or_predicate, **kwargs) // 期待出现某个响应时使用这里只举一个例子,更多请参考官方文档,https://playwright.dev/python/docs/api/class-page#page-wait-for-request:
page.goto("https://www.baidu.com")# 当出现请求地址地址包含www.baidu.com且响应状态为200时等待结束page.expect_response(lambda response: "www.baidu.com" in response.url and response.status == 200)123以上就是本次探究的一个总结,至于其它的浏览器操作自动化部分,不在这里敖述,网上一搜一大堆。这里推荐这篇博客:https://blog.csdn.net/zjkpy_5/article/details/122418811。
还有一个自动生成代码,类似于excel的宏录制的功能,这里不做探究,工具只是一个辅助,多动手去发现其中的规律才能巩固你的基础。————————————————版权声明:本文为CSDN博主「Anesthesia丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_36991535/article/details/124781189
posted @ 2023-03-23 10:54  爱洗澡的猫妹  阅读(1082)  评论(0编辑  收藏  举报