第7章 JavaScript动态渲染页面爬取

目录

  • 1. Selenium的使用
    • 1.1 准备工作
      • 安装selenium
      • 安装WebDriver
      • WebDriver配置
    • 1.2 基本用法
    • 1.3 初始化浏览器对象
    • 1.4 访问页面
    • 1.5 查找节点
      • 单个节点
      • 多个节点
    • 1.6 节点交互
    • 1.7 动作链
    • 1.8 运行JavaScript
    • 1.9 获取节点信息
      • 获取属性
      • 获取文本值
      • 获取ID、位置、标签名和大小
    • 1.10 切换Frame
    • 1.11 延时等待
      • 隐式等待
      • 显式等待
    • 1.12 前进和后退
    • 1.13 Cookie
    • 1.14 选项卡管理
    • 1.15 异常处理
    • 1.16 反屏蔽
    • 1.17 无头模式
  • 2. Splash的使用

1. Selenium的使用

  • 很大情况下Ajax请求会使用加密参数

    • token
    • sign
  • 示例:Scrape | Movie

    • Ajax接口包含token数据
  • 模拟Ajax请求的两种方式

    • 深挖逻辑
      • 把token参数的构造逻辑完全找出
      • 再用python代码复现
      • 构造Ajax请求
    • 直接模拟浏览器的运行(使用Selenium)
      • 绕过上方过程
      • 将呈现的数据直接爬取下来
  • Selenium

    • 自动化测试工具
    • 可以驱动浏览器完成特定的操作
      • 点击
      • 下拉
      • ···
    • 获取浏览器当前呈现的页面源代码

1.1 准备工作

安装selenium

pip install selenium

安装WebDriver

  • Edge为例
  • 下载地址:Microsoft Edge WebDriver - Microsoft Edge Developer

WebDriver配置

  • 将WebDriver的.exe文件放入Python的根目录下

1.2 基本用法

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWaitbrowser = webdriver.Edge()try:browser.get('https://baidu.com')input = browser.find_element(By.ID, 'kw')input.send_keys('Python')input.send_keys(Keys.ENTER)wait = WebDriverWait(browser, 10)wait.until(EC.presence_of_element_located((By.ID, "content_left")))print(browser.current_url)print(browser.get_cookies())print(browser.page_source)
finally:browser.close()

1.3 初始化浏览器对象

  • 电脑端浏览器
    • Chrome
    • Firefox
    • Edge
    • Safari
  • 手机端浏览器
    • Android
    • BlackBerry
from selenium import webdriverbrowser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.Safari()

1.4 访问页面

  • page_source:获取网页源码
from selenium import webdriverbrowser = webdriver.Edge()
browser.get("https://www.taobao.com")print(browser.page_source)
browser.close()

1.5 查找节点

单个节点

  • 获取淘宝网 - 淘!我喜欢 (taobao.com)的搜索框
  • 观察源码分析获取
from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.get("https://www.taobao.com")input_first = browser.find_element(By.ID, "q")
input_second = browser.find_element(By.CSS_SELECTOR, "#q")
input_third = browser.find_element(By.XPATH, "//*[@id=\"q\"]")print(input_first, input_second, input_third)browser.close()

多个节点

  • 获取淘宝网 - 淘!我喜欢 (taobao.com)左侧导航条的所有条目
from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.get("https://www.taobao.com")lis = browser.find_elements(By.CSS_SELECTOR, ".service-bd li")print(lis)browser.close()

1.6 节点交互

  • send_keys:输入文字
  • clear:清空文字
  • click:点击按钮
from selenium import webdriver
from selenium.webdriver.common.by import By
import timebrowser = webdriver.Edge()
browser.get('https://taobao.com')input = browser.find_element(By.ID, 'q')
input.send_keys('iPhone')time.sleep(1)input.clear()
input.send_keys("iPad")button = browser.find_element(By.CLASS_NAME, "btn-search")
button.click()

1.7 动作链

  • 拖拽节点
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChainsbrowser = webdriver.Edge()
browser.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable")browser.switch_to.frame("iframeResult")source = browser.find_element(By.CSS_SELECTOR, "#draggable")
target = browser.find_element(By.CSS_SELECTOR, "#droppable")actions = ActionChains(browser)
actions.drag_and_drop(source, target)
actions.perform()

1.8 运行JavaScript

from selenium import webdriverbrowser = webdriver.Edge()
browser.get("https://www.zhihu.com/explore")
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
browser.execute_script("alert(\"To Bottom\")")

1.9 获取节点信息

获取属性

from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.get("https://spa2.scrape.center/")logo = browser.find_element(By.CLASS_NAME, "logo-image")print(logo)
print(logo.get_attribute("src"))

获取文本值

from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.get("https://spa2.scrape.center/")input = browser.find_element(By.CLASS_NAME, "logo-title")print(input.text)

获取ID、位置、标签名和大小

from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.get("https://spa2.scrape.center/")input = browser.find_element(By.CLASS_NAME, "logo-title")print(input.id)
print(input.location)
print(input.tag_name)
print(input.size)

1.10 切换Frame

  • selenium打开网页后默认在父Frame中操作
  • 如果此时页面中有子Frame(iframe)需要使用switch_to.frame方法切换Frame
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementExceptionbrowser = webdriver.Edge()
browser.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable")browser.switch_to.frame("iframeResult")
try:logo = browser.find_element(By.CLASS_NAME, "logo")
except NoSuchElementException:print("NO LOGO")browser.switch_to.parent_frame()
logo = browser.find_element(By.CLASS_NAME, "logo")print(logo)

1.11 延时等待

  • selenium的get方法在网页框架加载结束后才会结束执行
  • 如果在get方法执行完毕时获取网页源代码,其结果可能不是浏览器完全加载完成的页面
    • 额外的Ajax请求
    • JavaScript渲染
  • 设置浏览器延时等待一定的时间,确保节点已经加载出来

隐式等待

  • 如果selenium没有在DOM中找到节点,将继续等待,在超出设定时间后,抛出找不到节点的异常
  • 在查找节点而节点没有立即出现时,隐式等待会先等待一段时间再查找DOM
from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.implicitly_wait(10)
browser.get("https://spa2.scrape.center/")input = browser.find_element(By.CLASS_NAME, "logo-image")
print(input)

显式等待

  • 指定要查找的节点和最长等待时间
  • 如果在规定时间内加载出了要查找的节点,就返回这个节点
  • 如果找到了规定时间依然没有加载出来,就抛出超时异常
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Edge()
browser.get("https://www.taobao.com/")wait = WebDriverWait(browser, 10)
input = wait.until(EC.presence_of_element_located((By.ID, "q")))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".btn-search")))print(input, button)
  • 等待条件
    • 详情见
      • 官方说明文档
      • EC包文件
等待条件含义
title_is标题是某内容
title_contains标题包含某内容
presence_of_element_located节点出现,参数为节点的定位元组
如(By.ID, “p”)
visibility_of_element_located节点可见,参数为节点的定位元组
visibility_of可见,参数为节点对象
presence_of_all_elements_located所有节点都出现
text_to_be_present_in_element某个节点的文本值中包含某文字
text_to_be_present_in_element_value某个节点值中包含某文字
frame_to_be_available_and_switch_to_it加载并切换
invisibility_of_element_located节点不可见
element_to_be_clickable按钮可点击
staleness_of判断一个节点是否仍在DOM中
可知页面是否已经刷新
element_to_be_selected节点可选择,参数为节点对象
element_located_to_be_selected节点可选择,参数为节点的定位元组
element_selection_state_to_be参数为节点对象及状态
相等返回True,否则返回False
element_located_selection_state_to_be参数为定位元组及状态
相等返回True,否则返回False
alert_is_present是否出现警告提示框

1.12 前进和后退

  • forward():前进
  • back():后退
from selenium import webdriver
import timebrowser = webdriver.Edge()
browser.get("https://www.baidu.com/")
browser.get("https://www.taobao.com/")
browser.get("https://www.python.org/")
browser.back()
time.sleep(10)
browser.forward()
browser.close()

1.13 Cookie

from selenium import webdriver
import timebrowser = webdriver.Edge()
browser.get("https://www.zhihu.com/explore")print(browser.get_cookies())browser.add_cookie({"name": "name", "domain": "www.zhihu.com", "value": "ABC"})
print(browser.get_cookies())# 如果不sleep可能因为有部分cookie还未加载,导致清空cookies是有cookie残留
time.sleep(5)browser.delete_all_cookies()
print(browser.get_cookies())

1.14 选项卡管理

from selenium import webdriver
import timebrowser = webdriver.Edge()
browser.get("https://www.baidu.com")# 开启一个新的选项卡
browser.execute_script("window.open()")print(browser.window_handles)browser.switch_to.window(browser.window_handles[1])
browser.get("https://www.taobao.com")time.sleep(1)browser.switch_to.window(browser.window_handles[0])
browser.get("https://python.org")

1.15 异常处理

  • 节点未找到的异常
from selenium import webdriver
from selenium.webdriver.common.by import Bybrowser = webdriver.Edge()
browser.get("https://www.baidu.com")
browser.find_element(By.ID, "hello")
  • 处理异常
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException ,NoSuchElementExceptionbrowser = webdriver.Edge()try:browser.get("https://www.baidu.com")
except TimeoutException:print("Time Out")try:browser.find_element(By.ID, "hello")
except NoSuchElementException:print("No Element")
finally:browser.close()

1.16 反屏蔽

  • 很多网站会对selenium进行检测,防止一些爬虫的恶意爬取
  • 检测原理
    • 检测当前浏览器窗口下的window.navigator对象中是否包含webdriver属性
      • 在正常使用浏览器时,这个属性应该是undefined
      • 一旦使用了selenium,它就会给window.navigator对象设置webdriver属性
    • 很多网站通过JavaScript语句判断是否存在webdriver属性
      • 如果存在就直接屏蔽
  • 示例网站:Scrape | Movie
  • 访问示例网站
from selenium import webdriverbrowser = webdriver.Edge()
browser.get("https://antispider1.scrape.center/")
  • 直接使用JavaScipt语句把webdriver属性置空
from selenium import webdriverbrowser = webdriver.Edge()
browser.get("https://antispider1.scrape.center/")
browser.execute_script("Object.defineProperty(navigator, \"webdriver\", {get: () => undefined})")
  • 确实将webdriver属性置空
    • 但是execute_script方法是在页面加载之后才调用JavaScript语句的,此时网页早在页面渲染之前就已经检测webdriver属性了
  • 使用CDP(Chrome Devtools Protocol,Chrome开发工具协议)解决
    • 可以实现在每个页面加载的时候执行JavaScript语句,将webdriver属性置空
  • 执行CDP的方法为Page.addScriptToEvaluateOnNewDocument
  • Edge Devtools Protocol是基于CDP的所以CDP使用方式在Edge Devtools Protocol上同样适用
from selenium import webdriver
from selenium.webdriver import EdgeOptionsoption = EdgeOptions()# 隐藏提示条
option.add_experimental_option("excludeSwitches", ["enable-automation"])# 隐藏自动化扩展信息
option.add_experimental_option("useAutomationExtension", False)browser = webdriver.Edge(options=option)
browser.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": "Object.defineProperty(navigator, \"webdriver\", {get: () => undefined})"})
browser.get("https://antispider1.scrape.center/")

1.17 无头模式

  • 使网站运行时不会弹出窗口
  • 减少一些资源的加载
  • 使用EdgeOptions对象开启Edge浏览器的无头模式
from selenium import webdriver
from selenium.webdriver import EdgeOptionsoption = EdgeOptions()
option.add_argument("--headless")browser = webdriver.Edge(options=option)
browser.set_window_size(1500, 800)
browser.get("https://www.baidu.com")
browser.get_screenshot_as_file("preview.png")

2. Splash的使用

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

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

相关文章

10、外观模式(Facade Pattern,不常用)

外观模式(Facade Pattern)也叫作门面模式,通过一个门面(Facade)向客户端提供一个访问系统的统一接口,客户端无须关心和知晓系统内部各子模块(系统)之间的复杂关系,其主要…

利用DateFormat、Date、Calendar等相关类,编程实现如下功能

(1)用户输入2个日期,第一个日期用整数形式输入,把输入的整数设置为日历对象1的年月日的值。第二个日期以字符串形式输入,形如“2022-10-25”,并设置为日历对象2的年月日的值。将2个日期以“xx年xx月xx日”的…

04、pytest运行多个测试用例

官方用例 目录结构 course_04 | |----subdir | | | |----sample03_test.py | | | |----test_sample04.py | |----sample02_test.py | |----test_sample01.py# content of test_sample01.pydef test_simple01():print("test simple01")assert 0# content of tes…

从零开始学习 JS APL(二):完整指南和实例解析

大家好!这里是关于JS APL第二部分的知识点和笔记以及练习题 目录 大家好!这里是关于JS APL第二部分的知识点和笔记以及练习题 我们分以下几点来说: 1、事件监听(绑定): 目标:能够给 DOM元素…

@PostConstruct使用详解

一、简介 在Spring应用程序中启动时,有时需要在所有Bean都已加载,初始化并准备好之后执行某些自定义代码。这时,Spring提供了一个可用的方式,即使用PostConstruct注解。这个注解用于标记一个方法,这个方法将在Bean初始…

操作系统——进程同步

目录 一、信号量相关函数 1. 创建信号量集 2. 获取信号量集 3. 等待、通知信号量集 4. 控制信号量集 二、简单进程同步 1. 创建信号量集 2. P操作 3. V操作 4. 删除信号量集 5. 测试: 三、生产者与消费者 1. 创建、删除共享内存及信号量集 2. 单一生产…

基于Eclipse+Mysql+Tomcat开发的 教学评价管理系统

基于EclipseMysqlTomcat开发的 教学评价管理系统 项目介绍💁🏻 随着教育信息化的发展,教学评价管理系统已经成为了学校、教育机构等场所必不可少的一部分。本项目是基于EclipseMysqlTomcat开发的一套教学评价管理系统,旨在帮助教育…

Android中的动态代理详解

在说动态代理之前,先来简单看下代理模式。代理是最基本的设计模式之一。它能够插入一个用来替代“实际”对象的“代理”对象,来提供额外的或不同的操作。这些操作通常涉及与“实际”对象的通信,因此“代理”对象通常充当着中间人的角色。 代…

2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-C

2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-C 目录 2024 年甘肃省职业院校技能大赛中职组 电子与信息类“网络安全”赛项竞赛样题-C 需要环境或者解析可以私信 (二)A 模块基础设施设置/安全加固(200 分&…

Qt Location中加载地图对象

在Qt Location中加载地图对象,你可以按照以下步骤进行操作: 1,首先,确保你已经安装了Qt Location模块,并在项目中包含了相应的头文件。在项目文件(.pro)中添加以下行: QT locatio…

MacOS M芯片 安装MySQL5.7教程

目录 1. 安装Homebrew1.1 快速安装1.2 检查是否安装成功 2. 通过Homebrew安装MySQL2.1 搜索 MySQL 版本2.2 安装MySQL 5.72.3 位置说明2.4 启动MySQL服务2.5 检查服务状态2.6 设置环境变量2.7 重置密码 3. 测试安装 1. 安装Homebrew 1.1 快速安装 /bin/bash -c "$(curl …

【接口测试】POST请求提交数据的三种方式及Postman实现

1. 什么是POST请求? POST请求是HTPP协议中一种常用的请求方法,它的使用场景是向客户端向服务器提交数据,比如登录、注册、添加等场景。另一种常用的请求方法是GET,它的使用场景是向服务器获取数据。 2. POST请求提交数据的常见编…

uniapp微信小程序解决绘制polygon结束时的问题

目录 一、前言 二、实现思路 三、结束标绘具体代码 1、在地图展示工具栏处判断工具按钮是否展示v-if"item.isshow" 2、data声明的工具按钮中新增结束标绘按钮 3、在按钮的点击事件中新增结束标绘的判断 4、判断绘制的线段个数是否大于等于三条,当满…

Python小案例:打印10以内的素数

解析 1、利用循环控制范围(1,100) 2、通过循环判断素数 3、利用标记法进行打印素数 代码 #求1——100之间的素数 for i in range(2,101):is_primeNum Truefor j in range(2,i):if i%j 0:# print(f"{i}不是素数")is_primeNum Falseif is_…

LeedCode刷题---双指针问题

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 双指针简介 常见的双指针有两种形式,一种是对撞指针,一种是左右指针。 对撞指针:一般用于顺序结构中&…

手机充电器市场分析:预计2028年将达到82亿美元

在5G时代飞速发展的今天,随着科技的进步、应用的发展以及人们对以智能手机、平板电脑、智能穿戴设备为代表的智能终端设备追求越来越高的品质和功能,智能终端设备产品的更新换代的速度越来越快,这也将给全球智能终端充储电产品市场带来更大的…

Mybatis相关API(Sqlsession和sqlsessionFactroy)

代码 private static SqlSessionFactory sqlSessionFactory;static { ​try { // 获得核心配置文件String resource "mybits-config.xml"; // 加载核心配置文件InputStream inputStream Resources.getResourceAsStream(resource…

在OSPF中使用基本ACL过滤路由信息示例

1、ACL的基本原理。 ACL由一系列规则组成,通过将报文与ACL规则进行匹配,设备可以过滤出特定的报文。设备支持软件ACL和硬件ACL两种实现方式。 2、ACL的组成。 ACL名称:通过名称来标识ACL,就像用域名代替IP地址一样,更…

SQL数据库知识点总结归纳

前后顺序可以任意颠倒,不影响库中的数据关系 关系数据库的逻辑性强而物理性弱,因此关系数据库中的各条记录前后顺序可以任意颠倒,不影响库中的数据关系 一名员工可以使用多台计算机(1:m),而一台计算机只能被一名员工使用(1:1),所以员工和计算机两个实体之间是一对多…

数字发射链路噪声系数核算方法、实例与matlab程序

前言 发射链路各器件噪声性能较差会影响发射信号信噪比,从而导致较高的误码率,通过定量的分析发射链路噪声系数与信噪比恶化的关系,能够在设计过程中进行合理的评估和处理。 一、发射链路噪声 发射链路的噪声从特性上可以大致分为&#xff1…