新一代爬取JavaScript渲染页面的利器-playwright(二)

news2024/11/20 12:44:04

接上文:新一代爬取JavaScript渲染页面的利器-playwright(一)
  上文我们主要讲了Playwright的特点、安装、基本使用、代码生成的使用以及模拟移动端浏览,这篇我们主要讲下Playwright的选择器以及常见的操作方法。

6.选择器

  我们可以把传入的字符串称为Element Selector,除了它已经支持的CSS选择器、XPath,Playwright还为它拓展了一些方便好用的规则,例如直接根据文本内容筛选,根据节点的层级结构筛选等。

  • 文本选择

  文本选择支持text=这样的语句进行筛选,例如:

page.click(“text=Log in”)

  该句代表点击文本内容是Log in的节点

  • CSS选择器

  例如根据id/class筛选:

page.click(“button”)
page.click(“nav-bar .contact-us-item”)

  根据特定的节点属性进行筛选:

page.click(“[data-test-login-button]”)
page.click(“[aria-label=‘Sign in’]”)

  • CSS选择器+文本值

  常用的方法是has-text和text,前者代表节点中包含指定的字符串,后者代表节点中的文本值和指定的字符串完全匹配,示例如下:

page.click(“article:has-text(‘playwright’)”)
page.click(“#nav-bar :text(‘Contact us’)”)

  • CSS选择器+节点关系

  CSS选择器还可以结合文本关系来筛选节点,例如指定另一个选择器,示例如下:

page.click(“.item-description:has(.item-promo-banner)”)

  这里选择的就是class为item-description的节点,且该节点还要包含class为item-promo-banner的子节点。
  另外还可以结合一些相对位置关系,例如使用right-of指定位于某个节点右侧的节点。

page.click(“input:right-of(:text(‘Username’))”)

  这里选择的就是一个input节点,并且该节点要位于Username的节点的右侧。

  • XPath

  XPath也是支持的,不过是xpath关键字需要我们自己来指定,示例如下:

page.click(“xpath=//button”)

7.常用操作方法

  下面介绍些一些常用的操作方法。例如click(点击),fill(输入)等等,这些方法都属于page对象,所有方法都可以从page对象的API文档查找。
  下面介绍几个常见的操作方法的用法。

  • 事件监听

  page对象提供一个on方法,用来监听页面中发生的各个事件,例如close,console,load,request,response等。
  这里我们监听response事件,在每次页面请求得到相应的时候会触发这个事件,我们可以设置回调方法来获取响应中的全部信息,示例如下:

from playwright.sync_api import sync_playwright

def on_response(response):
    print(f'State{response.status}:{response.url}')

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.on('response',on_response)
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    browser.close()

  可以看到输出结果如下;
在这里插入图片描述

  我们在创建page对象后,就开始监听response事件,同时将回调方法设置为on_response,其接收一个参数,然后输出响应中的状态码和链接。
  如果观察网页请求包内容可以发现,这个输出结果正好对应浏览器network中所有的请求和响应。
  这个网站的真实的数据都是Ajax加载的,同时Ajax请求中还带有加密参数,不容易轻易获取。但是有了on_response方法,如果我们想截取Ajax请求,是非常容易的。

from playwright.sync_api import sync_playwright

def on_response(response):
    if '/api/movie' in response.url and response.status == 200:
        print(response.json)


with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.on('response',on_response)
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    browser.close()

  可以看到我们通过on_response方法拦截了Ajax请求,直接拿到了响应结果,即使这个Ajax请求中有加密参数也不用担心,因为这里截获的是最后的请求结果。

  • 获取页面源代码

  调用page对象的content方法可以获取网页源码。

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    html = page.content()
    print(html)
    browser.close()

  运行结果就是页面源代码,然后可以再利用一些解析工具就可以提取到想要的信息了。

  • 页面点击

  实现页面点击的方法就是click方法,click方法的API定义如下:

page.click(selector,**kwargs)

  其中,必须传入的数据是selector,其他参数都是可选的。selector代表选择器,用来匹配想要点击的节点,如果有多个节点都匹配,只使用第一个。
  其他比较重要的参数如下:

  • click_count:点击次数,默认为1.

  • timeout:等待找到要点击节点的超时的时间,默认为30秒。

  • position:需要传入如一个字典,要带有x和y属性,代表点击位置相对节点左上角的偏移量。

  • force:即使按钮设置了不可点击,也要强制点击,默认是False。

  • 文本输入

  文本输入对应的方法是fill,其API定义如下:

page.fill(selector,value,**kwargs)

  第一个selector代表选择器,value代表输入的内容,还可以通过timeout参数查找对应节点的最长等待时间。

  • 获取节点属性

  除了操作节点本身,我们也可以获得节点的属性,方法是get_attribute。

page.get_attribute(selector,name,**kwargs)
  这个有两个必传参数,selector和name,name代表要获取属性的名称。示例如下:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    href = page.get_attribute('a.name','href')
    print(href)
    browser.close()

  这里调用了get_attribute方法,传入的selector参数值是a.name,代表查找class为name的a的节点,name的参数传入了href,输出结果如下。

/detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIx

  这里看到对应节点的href属性只输出了一条,因为如果匹配了多个节点,就只返回第一个。

  • 获取多个节点

  对于获取所有节点,我们可以使用query_selector_all方法来获取。它会返回节点列表,通过遍历得到单个节点后,可以调用上面介绍的针对单个节点的方法完成一些操作和获取属性。示例如下:

# 获取多个节点
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    elements = page.query_selector_all('a.name')
    for element in elements:
        print(element.get_attribute('href'))
        print(element.text_content())

    browser.close()

  这里通过query_selector_all方法获取了所有可以匹配得到的节点,每个节点对应一个ElementHandle对象,然后通过该对象的get_attribute和text_content得到节点的属性和文本。运行结果如下:
在这里插入图片描述

  • 获取单个节点

  多个节点用query_selector_all,那么单个节点自然就是query_selector,如果匹配到多个节点,那么就只返回第一个。
示例如下:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    element = page.query_selector('a.name')
    print(element.get_attribute('href'))
    print(element.text_content())
    browser.close()

  运行后可以看到只返回了第一个节点的信息。

  • 网络劫持

  利用route方法可以实现网络劫持和修改操作,例如修改request的属性,修改响应结果等。

from playwright.sync_api import sync_playwright
import re

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()

    def cancel_request(route,request):
        route.abort()

    page.route(re.compile(r"(\.png)|(\.jpg)"),cancel_request)
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')
    page.screenshot(path='no_picture.png')
    browser.close()

  这里调用了route方法,第一个参数通过正则表达式传入了URL路径,cancel_request 方法接收两个参数,一个是route,代表CallableRoute对象,另一个是request代表Request对象,这里我们直接调用CallableRoute对象的abort方法,取消了这次请求,导致最终的结果是取消全部图片的加载。结果截图如下图所示:
在这里插入图片描述
  我们在爬取的过程中只关心的是图片的url,图片是否加载出来并不重要,这样可以提高整个页面的加载速度,提高爬取效率。
  另外还可以利用这个功能对一些响应内容进行修改,例如我们可以将相应的结果直接修改为我们自定义的文本内容。
  我们先定义一个文本文件,命名demo.html,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hack Response</title>
</head>
<body>
    <h1>Hack Response</h1>
</body>
</html>

  代码编写如下:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()

    def modify_response(route,request):
        print(f"Modifying response for {request.url}")
        route.fulfill(path = "./demo.html")
        
    page.route('**/*', modify_response)
    page.goto('https://spa6.scrape.center')
    page.wait_for_load_state('networkidle')

    browser.close()

  这里我们使用callableRoute对象的fulfill方法指定了一个本地文件。
在这里插入图片描述
  这时可以看到响应结果已经被修改了,但是URL没有变,我们可以利用route方法,灵活的控制请求和响应的内容,从而在某些场景下达到某些目的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1358392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用PowerJob做任务调度模块

最近项目中使用了PowerJob做任务调度模块&#xff0c;感觉这个框架真香&#xff0c;今天我们就来深入了解一下新一代的定时任务框架——PowerJob&#xff01; 简介 PowerJob是基于java开发的企业级的分布式任务调度平台&#xff0c;与xxl-job一样&#xff0c;基于web页面实现…

宽压输入1.5KV隔离直流高压输出电源模块

GRC系列低成本小体积宽电压输入隔离高压模块电源&#xff0c;是一款业界的隔离稳压型DC-DC高电压转换器&#xff0c;可在宽范围波动的不稳定电压输入环境中运行&#xff0c;通过模块的内部调整电路可以生成隔离稳压的直流高电压输出。产品外壳采用铝壳喷塑防腐设计&#xff0c;…

RTU数据采集终端

在现代工业控制系统中&#xff0c;数据采集是一个至关重要的步骤。RTU(远程终端单元)作为一种常用的数据采集终端设备&#xff0c;不仅可以实现数据的采集和传输&#xff0c;还可以实现现场设备的远程监控和控制。 一、RTU数据采集终端的工作原理 RTU数据采集终端是一种将现场…

springboot社区养老服务系统设计与实现

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 研究背景 当…

Spring框架-入门(IOC,DI)

文章目录 Spring框架简介创建Spring项目理解IOC和DI&#xff1a;IOC控制反转示例pom.xmlPerson.javaapplicationContext.xmlPersonTest.java DI依赖注入传统的方式GreetingService.javaGreetingServiceImpl.javaGreetingTest.java 使用DI依赖注入GreetingService.javaGreetingS…

关于系统设计的一些思考

0.前言 当我们站在系统设计的起点&#xff0c;面对一个新的需求&#xff0c;我们该如何开始呢&#xff1f;这是许多处于系统分析与设计领域的新手常常思考的问题。有些人可能会误以为&#xff0c;只要掌握了诸如面向对象、统一建模语言、设计模式、微服务、Serverless、Servic…

电脑视频剪辑软件哪个好用

电脑视频剪辑软件是当今创作者不可或缺的工具之一&#xff0c;它们能够帮助我们在电脑上对视频进行编辑、剪辑、特效添加等操作&#xff0c;使我们的作品更加专业、精美。然而&#xff0c;在众多的视频剪辑软件中&#xff0c;该选择哪一个呢&#xff1f;本文将为你推荐2款非常好…

全网最细,接口+接口自动化测试面试题汇总(附回答)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、我们测试的接口…

vite 如何设置 pwa,让网页类似 app 那样运行,使用插件 vite-plugin-pwa

vite 如何设置 pwa&#xff0c;让网页类似 app 那样运行&#xff0c;使用插件 vite-plugin-pwa 一、概述 情况还是那么个情况&#xff0c;还是原来的项目 vue2 改为 vitetsvue3 遇到的问题&#xff0c;今天这个问题是如何 在 Vite 环境下设置 PWA。 PWA 就是网页应用可以像 a…

驱动芯片,预计未来几年将达到605亿美元的规模

驱动芯片是指驱动显示屏幕幕的芯片&#xff0c;其应用广泛&#xff0c;主要用于电脑、手机、电视、平板电脑和汽车等设备。全球驱动芯片市场分析&#xff1a; 据市场研究预测&#xff0c;未来几年内&#xff0c;全球驱动芯片市场将保持稳定增长&#xff0c;并达到605亿美元的规…

【萤火虫系列教程】2/5-Adobe Firefly 文字​生成​图像

文字​生成​图像 登录账号后&#xff0c;在主页点击文字生成图像的【生成】按钮&#xff0c;进入到文字生成图像 查看图像 在文字生成图像页面&#xff0c;可以看到别人生成的图像。 点击某个图像&#xff0c;就可以进入图像详情&#xff0c;可以看到文字描述。 生成图像 我…

电子化学品,预计2025年会增长到4302亿美元

电子化学品市场是一个庞大的细分市场&#xff0c;它包括了广泛的化学品种类&#xff0c;如涂料、塑料、精细化学品、农药和医药等。这个市场的发展相当迅速&#xff0c;下面我们将从全球市场和中国市场两个方面对其发展趋势进行分析。全球市场分析&#xff1a; 从全球市场的角度…

谷达冠楠:抖店创业初期需要注意哪些

随着互联网的发展&#xff0c;越来越多的人选择通过开设网店来实现创业梦想。而在众多的电商平台中&#xff0c;抖音小店因其独特的社交属性和巨大的流量优势&#xff0c;成为了许多人的首选。然而&#xff0c;抖店创业并非一帆风顺&#xff0c;初期需要注意的问题也不少。以下…

OHC堆外内存

JVM内存模型 先复习一波JVM的内存模型&#xff0c;线程共享的区域为堆、方法区|永久代&#xff0c;线程不共享的区域为栈、程序计数器。 对象创建的整体流程可以用一图描述 内存逃逸 逃逸分析是指分析指针动态范围的方法&#xff0c;它同编译器优化原理的指针分析和外形分析相…

小微企业是如何使用CRM辅助业务的?CRM功能汇总

小企业的成长取决于客户&#xff0c;因此实施有效的CRM管理系统至关重要。曾有数据机构调查发现&#xff0c;每支出1美元用于CRM&#xff0c;您的CRM将带来8、71美元的回报。难怪越来越多的企业实施CRM&#xff0c;因为它带来了高投资回报率。对小企业来说&#xff0c;CRM应该具…

pytorch08:学习率调整策略

目录 一、为什么要调整学习率&#xff1f;1.1 class _LRScheduler 二、pytorch的六种学习率调整策略2.1 StepLR2.2 MultiStepLR2.3 ExponentialLR2.4 CosineAnnealingLR2.5 ReduceLRonPlateau2.6 LambdaLR 三、学习率调整小结四、学习率初始化 一、为什么要调整学习率&#xff…

怎么查询网络出口IP

怎么查询自己的网络的出口IP 背景 一般跟第三方服务进行接口数据交互的时候&#xff0c;对方都会让我们提供调用接口的网络的出口IP&#xff0c;对方会把该IP地址加到对方的白名单中。这样我们才能有权限进行接口的访问。 解决办法 下面介绍三种常用的查询网络出口IP的办法…

DevOps(10)

目录 56.Docker的架构&#xff1f; 57.Docker镜像相关操作有哪些&#xff1f; 58.Docker容器相关操作有哪些&#xff1f; ​编辑59.如何查看Docker容器的日志&#xff1f; 60.如何启动Docker容器&#xff1f;参数含义&#xff1f; 61.如何进入Docker后台模式&#xff1f;有…

基于Java SSM框架实现旅游资源网站系统项目【项目源码+论文说明】

基于java的SSM框架实现旅游资源网站系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个旅游资源网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述旅…

Redis:原理+项目实战——Redis实战2(Redis实现短信登录(原理剖析+代码优化))

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理项目实战——Redis实战1&#xff08;session实现短信登录&#xff08;并剖析问题&#xff09;&#xff09…