您的当前位置:首页>全部文章>文章详情

【Python】第七章 JavaScript动态渲染页面爬取

CrazyPanda发表于:2023-12-03 22:00:44浏览:863次TAG:

目录


1. Selenium的使用

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

    • token

    • sign

  • 示例:Scrape | Movie

    • Ajax接口包含token数据

  • 模拟Ajax请求的两种方式

    • 绕过上方过程

    • 将呈现的数据直接爬取下来

    • 把token参数的构造逻辑完全找出

    • 再用python代码复现

    • 构造Ajax请求

    • 深挖逻辑

    • 直接模拟浏览器的运行(使用Selenium)

  • Selenium

    • 点击

    • 下拉

    • ···

    • 自动化测试工具

    • 可以驱动浏览器完成特定的操作

    • 获取浏览器当前呈现的页面源代码

1.1 准备工作

安装selenium

pip install selenium1

安装WebDriver

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 WebDriverWait

browser = 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 webdriver

browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.Safari()

1.4 访问页面

  • page_source:获取网页源码

from selenium import webdriver

browser = webdriver.Edge()
browser.get("https://www.taobao.com")

print(browser.page_source)
browser.close()

1.5 查找节点

单个节点

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = 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()

多个节点

from selenium import webdriver
from selenium.webdriver.common.by import By

browser = 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 time

browser = 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 ActionChains

browser = 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 webdriver

browser = 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 By

browser = 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 By

browser = 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 By

browser = 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 NoSuchElementException

browser = 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 By

browser = 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 EC

browser = 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 time

browser = 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 time

browser = 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 time

browser = 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 By

browser = 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 ,NoSuchElementException

browser = 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进行检测,防止一些爬虫的恶意爬取

  • 检测原理

    • 如果存在就直接屏蔽

    • 在正常使用浏览器时,这个属性应该是undefined

    • 一旦使用了selenium,它就会给window.navigator对象设置webdriver属性

    • 检测当前浏览器窗口下的window.navigator对象中是否包含webdriver属性

    • 很多网站通过JavaScript语句判断是否存在webdriver属性

  • 示例网站:Scrape | Movie

  • 访问示例网站

from selenium import webdriver

browser = webdriver.Edge()
browser.get("https://antispider1.scrape.center/")
  • 直接使用JavaScipt语句把webdriver属性置空

from selenium import webdriver

browser = 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 EdgeOptions

option = 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 EdgeOptions

option = 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的使用


猜你喜欢

【Python】如何在系统中安装pandas库
快速入门:Python安装pandas库的方法,需要具体代码示例一、概述Python是一种广泛使用的编程语言,它拥有强大的开发生态系统,其中包括许多实用的库。而pandas是其中一款非常受欢迎的数据分析库,它提供了高效的数据结构和数据分析工具,使得数据处理和分析变得更加简单。本文将介绍如何在Python中安装pandas库,并提供相应的代码示例。二、安装Python在安装pandas库之前,首先需要安装Python。Python官方网站提供了最新版本的Python的安装包,可以根据自己的操作系统
发表于:2024-01-09 浏览:300 TAG:
【Python】如何利用Python编写RSA加密算法
如何利用Python编写RSA加密算法?引言:RSA是一种非对称加密算法,被广泛应用于信息安全领域。在现代通信中,RSA加密算法常用于加密和解密敏感数据。本文将介绍如何使用Python编写RSA加密算法,并提供具体的代码示例。1. 安装Python库在开始编写RSA加密算法之前,需要安装Python的加密库。可以使用以下命令安装:pip install rsa2. 生成RSA密钥对在RSA加密算法中,存在公钥和私钥两个密钥。公钥用于加密数据,私钥用于解密数据。首先,我们需要生
发表于:2024-01-16 浏览:334 TAG:
【Python】学习Python人工智能库的核心技能,构建智能应用
打造智能应用:掌握Python人工智能库的核心技能,需要具体代码示例摘要:本文旨在介绍如何使用Python人工智能库开发智能应用。首先,我们将简要介绍Python人工智能库的重要性和应用领域。接下来,我们将重点介绍四个核心技能,包括数据处理、机器学习、深度学习和自然语言处理。我们将通过具体的代码示例和实践案例,深入讲解如何应用这些技能来打造智能应用。引言人工智能是当今科技界炙手可热的话题,而Python作为一种高效简洁的编程语言,拥有丰富的人工智能库,如NumPy、SciPy、TensorFlo
发表于:2024-01-02 浏览:369 TAG:
【Python】如何使用Python实现拓扑排序算法
如何使用Python实现拓扑排序算法?拓扑排序是图论中的一种排序算法,用于对有向无环图(DAG)进行排序。在拓扑排序中,图中的节点代表任务或事件,有向边表示任务或事件之间的依赖关系。在排序结果中,所有的依赖关系都被满足,每个节点都排在它的所有前驱节点之后。在Python中实现拓扑排序算法可以使用深度优先搜索(DFS)的思想来解决。下面是一个具体的代码示例:from collections import defaultdict   class Gr
发表于:2024-01-16 浏览:267 TAG:
【Python】pycharm环境如何配置
配置教程:1、下载并安装PyCharm;2、选择Python解释器;3、配置虚拟环境;4、配置代码风格;5、配置调试器;6、配置版本控制工具;7、配置插件;8、配置Python路径和环境变量;9、配置其他选项。详细介绍:1、从PyCharm官网下载适合电脑操作系统的安装包,然后按照提示完成安装;2、在PyCharm中,可以选择已有的Python解释器或者添加新的解释器等等。本教程操作系统:windows10系统、Python3.11.4版本、Dell G3电脑。PyCharm环境配置教程如下:下
发表于:2024-01-02 浏览:325 TAG:
【Python】如何用Python编写K-均值聚类算法
如何用Python编写K-均值聚类算法?K-均值聚类算法是一种常用的数据挖掘和机器学习算法,能够将一组数据按照其属性进行分类和聚类。本文将介绍如何用Python编写K-均值聚类算法,并提供具体的代码示例。在开始编写代码之前,我们需要了解K-均值聚类算法的基本原理。K-均值聚类算法的基本步骤如下:初始化k个质心。质心是指聚类的中心点,每个数据点都会被归到与其最近的质心所代表的类别。根据每个数据点与质心的距离,将其分配到最近的质心所代表的类别。更新质心的位置,将其设置为该类别中所有数据点的平均值。重
发表于:2024-01-16 浏览:270 TAG:
【Python】如何使用Python中的时间和日期模块
如何使用Python中的时间和日期模块导言:在编程中,处理时间和日期是非常常见的任务。Python提供了强大的时间和日期模块,使得处理时间和日期的操作变得更加简单和方便。本文将介绍Python中的时间和日期模块,并提供具体的代码示例,帮助读者更好地理解和应用它们。一、引入时间和日期模块Python内置的时间和日期模块是datetime模块,我们需要先引入该模块才能使用其中的函数和类。示例代码如下:import datetime登录后复制二、获取当前日期和时间如果我们想要获取当前日期和时
发表于:2024-01-22 浏览:294 TAG:
【Python】如何使用Python实现冒泡排序算法
如何使用Python实现冒泡排序算法?冒泡排序算法是一种简单但有效的排序算法,它的思想是不断比较相邻的两个元素,如果它们的顺序不正确,就将它们交换位置,直到整个序列都排好序为止。下面将通过具体的代码示例来演示如何使用Python实现冒泡排序算法。def bubble_sort(arr):     n = len(arr)     # 外层循环控制比较的轮数  &nbs
发表于:2024-01-16 浏览:317 TAG:
【Python】了解Django框架:从入门到精通
Django是一个流行的Python Web框架,它为开发Web应用程序提供了一种高效而强大的方式。本文将从入门到精通,介绍Django的基础知识,并提供具体代码示例。安装Django在使用Django之前,需要确保已在计算机上安装了Python。然后,可以使用以下命令安装Django:pip install Django创建Django项目要创建一个新的Django项目,可以使用以下命令:django-admin startproject <pro
发表于:2024-01-19 浏览:301 TAG:
【Python】如何使用Python中的数据分析库进行数据处理
如何使用Python中的数据分析库进行数据处理人们越来越重视数据处理和分析的重要性。随着电子设备的不断普及和互联网的发展,我们每天都会产生大量的数据。要从这些海量的数据中提取有用的信息和洞察,就需要使用强大的工具和技术。Python作为一种流行的编程语言,有许多优秀的数据分析库,如Pandas、NumPy和Matplotlib等,可以帮助我们高效地进行数据处理和分析。本文将介绍如何使用Python中的数据分析库进行数据处理。我们将重点介绍Pandas库,因为它是用于数据处理和分析的最常用和最强大
发表于:2024-01-20 浏览:312 TAG: