动态渲染页面爬取

04- 动态渲染页面爬取

4-1 Selenium的安装

Selenium是一个自动化测试工具,利用它可以驱动浏览器执行特定的动作,如点击、下拉等操作,同时还可以获取浏览器当前呈现的页面的源代码,做到可见即可爬。对于一些JavaScipt动态渲染的页面来说,此种抓取方式非常有效。

4 -2 Selenium相关链接

4-3 pip 安装

pip install selenium

4-4 ChromeDriver 的安装

安装ChromeDriver。因为只有安装ChromeDriver.才能驱动Chrom浏览器完成相对应的操作

4-5 ChromeDriver 的相关链接

4-6 ChromeDriver环境配置

在Windows下,建议直接将chromedriver.exe文件拖到Python的根目录下

在配置Python的时候系统会自动把Python配置到环境中,到时候我们可以直接使用驱动就可以不用写路径问题

4-7 Selenium声明浏览器对象

Selenium支持多种的浏览器,如chrome、Firefox、Edge等

# @Time : 2020/5/11 15:01 
# @Author : SmallJ

# 支持的浏览器
from selenium import webdriver

browser = webdriver.Chrome()
borwser = webdriver.Android()
borwser = webdriver.Firefox()
borwser = webdriver.Ie()

4-8 Selenium访问页面

我们可以用get()方法来请求网页,参数传入链接URL即可。

  • get : 请求的网址
  • page_source : 为反映页面源代码
  • close : 为关闭浏览器
# @Time : 2020/5/11 15:01 
# @Author : SmallJ

# 支持的浏览器
from selenium import webdriver

# 实例化浏览器
browser = webdriver.Chrome()

# 用browser这个对象来发送请求
url = 'https://www.taobao.com/'
browser.get(url)

# page_source 为页面源代码
# 用browser这个对象来获取页面源代码
html = browser.page_source
print(html)

# close 为关闭浏览器
browser.close()

4-9 Selenium查找节点

  • 单个节点
语法 描述
find_element_by_id 根据页面中的id属性来查找值
find_element_by_xpath 根据xpath语法来进行查找值
find_element_by_link_text 根据文本来进行查询
find_element_by_partial_link_text 根据文本进行查询模糊查询
find_element_by_name 根据name属性来进行查询
find_element_by_class_name 根据class属性来进行查询
find_element_by_css_selector 根据css语法来进行查找
  • 多个节点
    • 注意 : 多节点在这个方法的名称中,elment多了一个s。注意区分

Selenium可以驱动浏览器完成各种操作,比如填充表单、模拟点击等。比如,我们想要完成向某个输入框输入文字的操作,总需要知道

from selenium import webdriver
import time

browser = webdriver.Chrome()
url = 'https://www.taobao.com/'
browser.get(url)

# 根据id来进行查找 
first_input = browser.find_element_by_id('q')

# 根据css来进行查找
second_input = browser.find_element_by_css_selector('#q')

# 根据Xpath来进行查找
three_input = browser.find_element_by_xpath('//*[@id="q"]')


# 关闭浏览器
browser.close()

这里我们使用3种方式获取输入框,分别是根据ID、CSS选择器、XPath获取

另外,Selenium还提供了通过方法find_element(),它需要传入两个参数:查找方式和By值。实际上,它就是find_element_by_id()这种方法的通过函数版本,比如 **find_element_by_id(id) ** 等价于 **find_element(By.ID)**两者的结果是一样。

京东

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

# 实例化对象
browser = webdriver.Chrome()

# 请求url
url = 'https://www.jd.com/'
browser.get(url)

time.sleep(3)

# 单节点查找
# 查找京东的搜索框
browser.find_element(By.ID, 'key').send_keys('Python人工智能')

# 查找点击按钮并进行点击事件
browser.find_element(By.XPATH, '//*[@id="search"]/div/div[2]/button/i').click()

time.sleep(5)
# 关闭浏览器
browser.close()

淘宝

from selenium import webdriver
import time

browser = webdriver.Chrome()

url = 'https://www.taobao.com/'
browser.get(url)
time.sleep(5)
# 单个节点
# 查找节点采用find来进行查找
# 在输入框输入Python   send_keys 为输入内容
browser.find_element_by_css_selector('#q').send_keys('Python')

# 定位到搜索框,并进行点击事件 click为点击事件
browser.find_element_by_xpath('//*[@id="J_TSearchForm"]/div[1]/button').click()

time.sleep(5)
browser.close()

4-10 Selenium节点交互

Selenium可以驱动浏览器来执行一些操作,也就是说可以让浏览器去模拟人的行为去执行一些操作。比较常见的操作用法有:输入文字时用send_keys()方法,清空文字时用clear()方法,点击按钮用click()方法

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

browser = webdriver.Chrome()

url = 'https://www.taobao.com/'
browser.get(url)

time.sleep(2)

input = browser.find_element(By.ID, 'q')

# 输入内容
input.send_keys('Python')

# 清空内容
input.clear()

# 强制停止两秒
time.sleep(2)

input.send_keys('Python人工智能')

button = browser.find_element(By.XPATH, '//*[@id="J_TSearchForm"]/div[1]/button')

# 进行点击事件
button.click()

# 强制等待
time.sleep(2)

# 关闭浏览器
browser.close()

4-11 Selenium动作链

在上面的实例中,一些交互动作都是针对某个节点执行的。比如,对于输入框,我们就调用它的输入文字和清空文字方法;对于按钮,就调用它的点击方法。其实,还有另外一些操作,它们没有特定的执行对象,比如鼠标拖拽、键盘按钮等,这些动作用另外一种方式来执行,那就是动作链。

  • drag_and_drop(source, target) :
    • drop :中文意思起点
    • drag : 中文意思结束
    • source : 为要拖拽元素的起点
    • target : 为要拖拽元素的终点
  • perform(self)
    • 该方法为执行动作
# @Time : 2020/5/11 20:50 
# @Author : SmallJ 

from selenium import webdriver
from selenium.webdriver import ActionChains
import time

# ActionChains为动作链
url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'

browser = webdriver.Chrome()

browser.get(url)

# 该请求的页面中存在页面嵌套所以需使用switch_to.frame
# switch_to.frame 为页面嵌套 根据id来取值
# 切换到页面嵌套
browser.switch_to.frame('iframeResult')


# 元素定位
# 请拖住我   source 中文意思 源代码
source = browser.find_element_by_css_selector('#draggable')


# 元素定位
# 请放置到这里   target 中文意思 目标
target = browser.find_element_by_css_selector('#droppable')

time.sleep(3)

# 进行实例化动作行为链
actions = ActionChains(browser)

# drag_and_drop
# source : 为拖拽元素的起点
# target : 为拖拽元素的终点
actions.drag_and_drop(source, target)

# perform 为方法执行动作
actions.perform()

首先,打开网页中的一个拖拽实例,然后依次选中要拖拽的节点和拖拽到目标节点,接着声明ActionChains对象并将其赋值为actions变量的drag_and_drop()方法,再调用perform()方法执行动作,此时就完成了拖拽操作。

4-12 Selenium执行JavaScript

对于某些操作,Selenium API并没有提供。比如,下拉进度条,它可以直接模拟运行JavaScipt此时使用execute_script()方法即可实现

# @Time : 2020/5/12 0:31 
# @Author : SmallJ 

from selenium import webdriver

url = 'https://www.zhihu.com/explore'

browser = webdriver.Chrome()
browser.get(url)
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("TO Bottom")')

4-13 Selenium获取节点信息

语法 描述
get_attribute() 获取属性值
get_text() 获取文本值
get_id 获取节点
get_location 获取节点在页面中的相对位置
tag_name 获取标签名称
size 获取节点大小

前面说过,通过page_source 属性可以获取网页源代码可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Souppyquery等)来提取信息

不过,既然Selenium已经提供了选择节点的方法,返回的是WebElement类型,那么它也有相关的方法和属性来直接提取节点信息,如属性、文本等。这样的话,我们就可以不用通过解析源代码来提取信息了。

  • 获取属性

我们可以使用get_attribute()方法来获取节点的属性,但是其前提是先选其中的这个节点。

# @Time : 2020/5/12 14:53 
# @Author : SmallJ
# ActionChains 为动作行为链

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

browser = webdriver.Chrome()

url = 'https://www.zhihu.com/explore'

# 请求该网页
browser.get(url)

# 查找属性
logo = browser.find_element(By.CLASS_NAME, 'Input')
print(logo)
print(logo.get_attribute('placeholder'))

4-14 Selenium切换Frame

我们知道网页中有一种节点叫作iframe,也就是子Frame,相当于页面的子页面,它的结构和外部网页内容的结构完全一致。Selenium打开页面后,它的默认是在父级Frame里面的操作,而此时如果页面中还有子Frame,它是不能获取子Frame里面的节点。这时就需要使用switch_to.frame()方法来切换Frame。

# @Time : 2020/5/12 15:21 
# @Author : SmallJ 

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.common.exceptions import NoSuchElementException


url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser = webdriver.Chrome()
browser.get(url)
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)
print(logo.text)

首先通过switch_to.frame()方法切换到子Frame里面,然后尝试获取子Frame里的logo节点(这是不能找到的)如果找不到的话,就会抛出NoSuchElementException异常,异常被捕捉之后,就会输出NO LOGO。接下来,重新切换到父级Frame然后再次重新获取节点。

3-15 延时等待

隐式等待

当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。换句话说,当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间再查找DOM,默认的时间为0秒

# @Time : 2020/5/12 16:02 
# @Author : SmallJ 

from selenium import webdriver

browser = webdriver.Chrome()
url = 'https://www.baidu.com/'

# 隐式等待
# 隐式等待的含义就是超出时间的范围的时候就不会继续查找,抛出异常
# time_to_wait : 为时间
browser.implicitly_wait(10)

browser.get(url)
input = browser.find_element_by_id('wrapper_wrapper')
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.Chrome()
url = 'https://www.taobao.com/'
browser.get(url)

# WebDriverWait 里面传递两个参数
# driver 引擎
# timeout 为超时时间
wait = WebDriverWait(browser, 10)
input_data = 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_data, button)

  • 这里首先引入WebDriverWait这个对象,指定最长等待时间,然后调用它的until()方法,传入要等待条件expected_conditions。比如,这里传入了presence_of_element_located这个条件,代表节点出现的意思,其参数是节点的定位元组,也就是ID为q的节点搜索。
  • 这样可以做到的效果就是,在10秒内如果ID为element_to_clickable,也就是可点击,所以查找按钮时查找CSS选择器为.btn-search的按钮,如果10内它是可点击的,也就是成功加载出来了,也就是返回这个按钮节点。
  • 如果超过10秒还不可以点击,就抛出异常。

猜你喜欢

转载自blog.csdn.net/qq_37662827/article/details/106098993