1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 爬虫——动态渲染页面抓取

爬虫——动态渲染页面抓取

时间:2023-09-20 06:06:05

相关推荐

爬虫——动态渲染页面抓取

文章目录

Selenium的使用Chrome浏览器配置ChromeDriver声明浏览器对象,初始化访问页面节点查找多个节点节点交互,操作动作链,拖拽,按钮执行JavaScript,进度条获取节点属性、文本、位置、id、大小、标签名切换Frame——略257延时等待隐式等待显式等待前进和后退Cookies选项卡管理异常处理Splash的使用——262略使用Selenium爬取某页面商品——289略

一些网站分页部分是JavaScript生成的的,不是HTML源码,也不是Ajax请求

Selenium的使用

Selenium是自动化测试工具,可以驱动浏览器执行特定的动作,如单击、下拉等,同时可以获取浏览器当前呈现的源代码,做到可见即可爬

Chrome浏览器配置ChromeDriver

首先需要安装好Chrome浏览器并且配置好ChromeDriver。ChromeDriver文件在网址/mirrors/chromedriver/中下载,下载Chrome浏览器对应的版本,在Chrome浏览器中,选择设置->帮助->关于chrome可以查看其版本

找到后在网址中下载对应版本的文件下载,最后解压复制到python软件对应的文件中

基本使用

from selenium import webdriverfrom mon.by import Byfrom mon.keys import Keysfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWaitbrowser = webdriver.Chrome()try:browser.get('')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_all_elements_located((By.ID, 'content_left')))print(browser.current_url)print(browser.get_cookies())print(browser.page_source)finally:browser.close()

运行后会自动弹出Chrome浏览器,浏览器先跳到百度,在跳到搜索框输入Python,接着跳到搜索页面,结束后在控制台输出当前的URL、当前的Cookies和网页代码。当前的URL、当前的Cookies和网页代码都是浏览器中的真实内容。所以说使用Selenium来加载网页可以直接拿到JavaScript渲染的结果。

声明浏览器对象,初始化

Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器,另外也支持无界面浏览器PhantomJS。可以用如下方式初始化:

from selenium import webdriverbrowser = webdriver.Chrome()browser = webdriver.Firefox()browser = webdriver.Edge()browser = webdriver.PhantomJS()browser = webdriver.Safari()

初始化之后就是调用browser,让其执行各个动作以模拟浏览器操作

访问页面

调用get方法请求网页,传入URL即可

from selenium import webdriverbrowser = webdriver.Chrome()browser.get('/')print(browser.page_source)browser.close()

运行后浏览器自动访问某页面,然后输出其源代码,最后关闭浏览器

节点查找

Selenium可以驱动浏览器完成各种操作,比如填充表格、模拟点击等。比如,我们要向某输入框输入文字操作,需要知道输入框位置,Selenium提供了一系列查找节点的方法,我们可以用该方法找到需要的节点

单节点

比如需要从某网站提取搜索框这个节点,,首先需要看其源代码

可以发现,它的id是q,name也是q,此外,还有许多其他属性,此时可以用多种方法获取它了,比如,find_element_by_name()是根据name值获取,find_element_by_id()是根据id值获取,另外,还可以根据XPath、CSS选择器等方式获取

from selenium import webdriverbrowser = webdriver.Chrome()browser.get('/')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)print(input_second)print(input_third)browser.close()

3种获取方式分别是根据ID、CSS选择器和XPath,三个输出是一样的结果

所有获取单节点的方法:

browser.find_element_by_id()browser.find_element_by_name()browser.find_element_by_xpath()browser.find_element_by_link_text()browser.find_element_by_partial_link_text()browser.find_element_by_tag_name()browser.find_element_by_class_name()browser.find_element_by_css_selector()

还有一个通用方法,find_element(),需要两个参数:查找方式By和值,它是上面方法的通用模板find_element_by_id(id)就等价于find_element(By.ID,id)

browser.find_element_by_id('q')browser.find_element(By.ID, 'q') # 两者等效

多个节点

如果网站有多个节点,find_element()方式只能获取第一个,要获取多个需要find_elements(),与之前的方法多了一个s,该方法返回多个节点,其结果为列表形式,其他方法也和上面的类似,多一个s

所有获取多个节点的方法:

browser.find_elements_by_id()browser.find_elements_by_name()browser.find_elements_by_xpath()browser.find_elements_by_link_text()browser.find_elements_by_partial_link_text()browser.find_elements_by_tag_name()browser.find_elements_by_class_name()browser.find_elements_by_css_selector()

节点交互,操作

输入文字用send_keys(),清空文字用clear(),点击按钮用click(),都是针对节点的动作操作

from selenium import webdriverimport timebrowser = webdriver.Chrome()browser.get('/')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()

这段代码先驱动浏览器打开某网页,然后用find_element_by_id()方法获取输入框,然后用send_keys()输入文字iPhone,等待1s后用clear()清除,再用send_keys()输入文字iPad,之后再用find_element_by_class_name()获取按钮,最后用click()完成搜索

更多操作在https://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.remote.webelement中

动作链,拖拽,按钮

动作链没有特定的执行对象,比如鼠标拖拽、键盘按键等。现在实现一个节点的拖拽操作,将某节点从一处拖拽到另一处:

from selenium import webdriverfrom selenium.webdriver import ActionChainsbrowser = webdriver.Chrome()url = '/try/try.php?filename=jqueryui-api-droppable'browser.get(url)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()

打开拖拽实例的网页,获取需要拖拽目标和拖拽到的目标节点,声明ActionChains对象,用drag_and_drop()方法,再用perform()方法执行,此时完成了操作,更多动作链在https://selenium-python.readthedocs.io/api.html#module-mon.action_chains

执行JavaScript,进度条

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

from selenium import webdriverbrowser = webdriver.Chrome()url = '/explore'browser.get(url)browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')browser.execute_script('alert("To Bottom")')

这里利用execute_script()方法将进度条下拉到最底部,然后弹出alert提示框

获取节点属性、文本、位置、id、大小、标签名

通过page_source()方法可以获取网页的源代码,接着使用解析库(正则表达式、Beautiful Soup、pyquery等)提取信息

get_attribute()方法获取节点属性,前提是先获取节点

from selenium import webdriverbrowser = webdriver.Chrome()url = '/explore'browser.get(url)loge = browser.find_element_by_class_name('AppHeader-login') #获取节点print(loge)print(loge.get_attribute('class')) # 获取节点的class属性值print(loge.text)# 获取文本print(loge.id) # 获取id属性print(loge.location) # 获取节点相对位置print(loge.tag_name) # 获取标签名称print(loge.size)# 获取节点大小

<selenium.webdriver.remote.webelement.WebElement (session="b218b4c59af7ca49d37f0afc3d440353", element="c9480ef7-e341-4289-af5f-c5fd40e626d1")>Button AppHeader-login Button--blue登录c9480ef7-e341-4289-af5f-c5fd40e626d1{'x': 848, 'y': 9}button{'height': 34, 'width': 62}

切换Frame——略257

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

import timefrom selenium import webdriverfrom mon.exceptions import NoSuchElementExceptionbrowser = webdriver.Chrome()url = '/explore'browser.get(url)browser.switch_to.frame(browser.find_element_by_class_name('AppHeader-login'))try:loge = browser.find_element_by_class_name('SignFlow-tab')print(loge.text)except NoSuchElementException:print('NO LOGO')browser.switch_to.parent_frame()logo = browser.find_element_by_class_name('AppHeader-login')print(logo)print(logo.text)

延时等待

获取的源码不一定是加载完全的页面,如果有额外的Ajax请求,在网页源码中也不一定成功获取到,这里需要延时等待一定的时间,确保节点已经加载出来

隐式等待

没有找到节点时将继续等待,超过设定时间后,抛出找不到节点的异常,默认为0

from selenium import webdriverbrowser = webdriver.Chrome()browser.implicitly_wait(10)url = '/explore'browser.get(url)input = browser.find_element_by_class_name('AppHeader')print(input)

隐式等待不太好,只设定一个固定时间,页面的加载时间会受到网络条件的影响

显式等待

指定要查找的节点,然后指定最长等待时间,加载出来了则返回该节点,没加载出来则抛出异常

from selenium import webdriverfrom mon.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECbrowser = webdriver.Chrome()url = '/'browser.get(url)wait = WebDriverWait(browser,10) # 等待最长时间# 传入要等待的条件,这个条件是代表节点出现的意思,参数是节点定位元组,也就是ID为q的节点搜索框input = wait.until(EC.presence_of_element_located((By.ID, 'q')))# 对于按钮,这里element_to_be_clickable,也就是可点击,规定时间内如果加载出来可点击则返回该按钮,否则抛出异常button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))print(input, button)

前进和后退

import timefrom selenium import webdriverbrowser = webdriver.Chrome()browser.get('')browser.get('')browser.get('/explore')browser.back()time.sleep(1)browser.forward()browser.close()

依次进入第一个第二个第三个链接,通过back退到第二个链接,通过forward进入第三个链接

Cookies

可以获取。添加、删除Cookies等

from selenium import webdriverbrowser = webdriver.Chrome()browser.get('/explore')print(browser.get_cookies())browser.add_cookie({'name':'name','domain':'','value':'germey'})print(browser.get_cookies())browser.delete_all_cookies()print(browser.get_cookies())

[{'domain': '.', 'httpOnly': False, 'name': 'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49', 'path': '/', 'secure': False, 'value': '1623166486'}, {'domain': '.', 'expiry': 1654702486, 'httpOnly': False, 'name': 'Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49', 'path': '/', 'secure': False, 'value': '1623166486'}, {'domain': '', 'httpOnly': False, 'name': 'KLBRSID', 'path': '/', 'secure': False, 'value': 'cdfcc1d45d024a211bb7144f66bda2cf|1623166485|1623166484'}, {'domain': '.', 'expiry': 1717774484, 'httpOnly': False, 'name': 'd_c0', 'path': '/', 'secure': False, 'value': '"ALBdCGskOxOPToZhl7eBwzfsYafP2OO7C_U=|1623166484"'}, {'domain': '.', 'httpOnly': False, 'name': '_xsrf', 'path': '/', 'secure': False, 'value': 'ffacba1a-baee-4096-b59c-8efeee2f4950'}, {'domain': '.', 'expiry': 1686238484, 'httpOnly': False, 'name': '_zap', 'path': '/', 'secure': False, 'value': 'e3476d66-1a88-4ef5-a95e-054aa925668b'}][{'domain': '.', 'httpOnly': False, 'name': 'name', 'path': '/', 'secure': True, 'value': 'germey'}, {'domain': '.', 'httpOnly': False, 'name': 'Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49', 'path': '/', 'secure': False, 'value': '1623166486'}, {'domain': '.', 'expiry': 1654702486, 'httpOnly': False, 'name': 'Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49', 'path': '/', 'secure': False, 'value': '1623166486'}, {'domain': '', 'httpOnly': False, 'name': 'KLBRSID', 'path': '/', 'secure': False, 'value': 'cdfcc1d45d024a211bb7144f66bda2cf|1623166485|1623166484'}, {'domain': '.', 'expiry': 1717774484, 'httpOnly': False, 'name': 'd_c0', 'path': '/', 'secure': False, 'value': '"ALBdCGskOxOPToZhl7eBwzfsYafP2OO7C_U=|1623166484"'}, {'domain': '', 'httpOnly': False, 'name': 'SESSIONID', 'path': '/', 'secure': False, 'value': '4my1bkPyu32JKCW7ak2XK3y7WlN7P255Xenq7bntxx4'}, {'domain': '.', 'httpOnly': False, 'name': '_xsrf', 'path': '/', 'secure': False, 'value': 'ffacba1a-baee-4096-b59c-8efeee2f4950'}, {'domain': '.', 'expiry': 1686238484, 'httpOnly': False, 'name': '_zap', 'path': '/', 'secure': False, 'value': 'e3476d66-1a88-4ef5-a95e-054aa925668b'}][]

选项卡管理

import timefrom selenium import webdriverbrowser = webdriver.Chrome()browser.get('/') # 访问百度browser.execute_script('window.open()') # 开启新的选项卡print(browser.window_handles)browser.switch_to_window(browser.window_handles[1]) # 切换到新选项卡,参数为选项卡代号browser.get('/')time.sleep(1)browser.switch_to_window(browser.window_handles[0]) # 会到第一个选项卡browser.get('/explore')

异常处理

from selenium import webdriverfrom mon.exceptions import TimeoutException, NoSuchElementExceptionbrowser = webdriver.Chrome()try:browser.get('/')except TimeoutException:print('Time Out')try:browser.find_element_by_id('hello')except NoSuchElementException:print('No Element')finally:browser.close()

Splash的使用——262略

作用:

异步方式处理多个网页的渲染过程

获取渲染后的页面的源代码或截图

通过关闭图片渲染或者使用Adblock规则来加快页面渲染速度

可执行特定的JavaScript脚本

可通过Lua脚本来控制页面渲染过程

获取渲染的详细过程并通过HAR格式呈现

使用Selenium爬取某页面商品——289略

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。