动态网页爬虫
一、动态网页爬虫方案介绍
1. 什么是动态网页
(1)动态网页,是网站在不重新加载的情况下,通过ajax技术动态更新网站中的局部数据。比如拉勾网的职位页面,在换页的情况下,url是没有发生改变的,但是职位数据动态地更改了
(2)ajax(异步JavaScript和XML)。用来描述一种使用现有技术集合的‘新’方法,包括: HTML 或 XHTML, CSS, JavaScript, DOM, XML, XSLT, 以及最重要的XMLHttpRequest。使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。
2. 动态网页爬虫的解决方案
(1)直接分析ajax调用的接口,然后通过代码请求这个接口
(2)使用Selenium+chromedriver模拟游览器行为获取数据
方式优点缺点分析接口直接可以请求到数据,不需要做一些解析工作,代码量少,性能高分析接口比较复杂,特别是一些通过js混淆的接口,要有一定的js功底,容易被发现是爬虫selenium直接模拟游览器的行为,游览器能请求到的,使用selemium也能请求到,爬虫更稳定代码量多,性能低
二、Selenium+chrome
1. selenium和chromedriver的基本使用
(1)Selenium+chrome介绍
Selemium相当于是一个机器人,可以模拟人类在游览器上的一些行为,自动处理游览器上的一些行为,比如点击、填充数据、删除cookie等。chromedriver是一个驱动Chrome游览器的驱动程序,使用它才可以驱动游览器,当然,针对不同的游览器会有不同的driver,下面列举几个游览器的driver:
- Chrome:https://chromedriver.storage.googleapis.com/index.html
- Edge:https://developer.microsoft.com/zh-cn/microsoft-edge/tools/webdriver/
- Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/
selenium的官方网址:https://selenium-python.readthedocs.io/
(2)安装selenium和webdriver
- 安装selenium:在Python终端安装即可,pip install selenium
- 安装chromedriver:上面已提供相应的网址,我们可以通过查看chrome的版本下载对应的驱动程序即可,下载完之后放到不需要权限的纯英文目录下即可
(3)selenium的基本使用
现在以一个简单的获取百度首页的例子来讲下selenium和chromedriver如何快速入门
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
# chromedriver的绝对路径
service = Service('D:\chromedriver\chromedriver.exe')# 初始化一个driver,并且指定chromedriver的路径
driver = webdriver.Chrome(service=service)# 请求网页
driver.get("https://www.baidu.com/")
2. selenium关闭页面和游览器
- **driver.close()**:关闭当前页面
- **driver.quit()**:退出整个游览器
3. selenium定位元素
需要导入模块:from selenium.webdriver.common.by import By
定位方法介绍driver.find_element(by=By.ID, value=" ")根据id查找某个元素driver.find_element(by=By.CLASS_NAME, value=" ")根据类名查找元素find_element(by=By.NAME,value=" ")根据name属性的值查找元素find_element(by=By.TAG_NAME,value=" ")根据标签名来查找元素find_element(by=By.XPATH,value=" ")根据xpath语法来获取元素find_element(by=By.CSS_SELECTOR,value=" ")根据css选择器选择元素
- 注意,find_element是获取第一个满足条件的元素,find_elements是获取第所有满足条件的元素
示例代码如下:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
service = Service(r"D:\chromedriver\chromedriver.exe")
driver = webdriver.Chrome(service=service)
driver.get("https://www.baidu.com/")
inputTag = driver.find_element(by=By.ID, value="kw")
inputTag.send_keys("python")
inputTag1 = driver.find_element(by=By.CLASS_NAME, value="s_ipt")
inputTag1.send_keys("python")
inputTag2 = driver.find_element(by=By.NAME, value="wd")
inputTag2.send_keys("python")
inputTag3 = driver.find_element(by=By.TAG_NAME, value="input")
inputTag3.send_keys("python")
inputTag4 = driver.find_element(by=By.XPATH, value="//input[@id='kw']")
inputTag4.send_keys("python")
inputTag5 = driver.find_element(by=By.CSS_SELECTOR, value="#form #kw")
inputTag5.send_keys("python")
4. selenium操作表单元素
(1)什么是表单元素
举个例子就能很好解释,如下图,像这些需要点击或者填写的就是表单元素
(2)操作表单元素
- 操作输入框:第一步,找到该元素;第二步:使用send_keys(value),将数据填充进去,示例代码如下:
inputTag = driver.find_element(by=By.ID, value="kw")
inputTag.send_keys("python")
- 操作checkbox:因为要选中checkbox标签,在网页中是需要通过鼠标点击的,因此想要选中checkbox标签,就需要先选中这个标签,然后执行click事件。示例代码如下:
submit = driver.find_element(by=By.CLASS_NAME, value="SignFlow-submitButton")
submit.click()
- 选择select:select元素不能直接点击,因为点击后还需要选中元素,这时候selenium就专门为select标签提供了一个类selenium.webdriver.support.Select。将获取到的元素当成参数传到这个类中,创建这个对象,以后就可以使用该对象进行选择了。示例代码如下:
# 需要导入的模块from selenium.webdriver.support.ui import Select
select = Select(driver.find_element(by=By.ID, value="menu-item-22898"))
select.select_by_index(0)
- select_by_index:按索引进行选择
- select_by_value:按值进行选择
- select_by_visible_text:按可见文本进行选择
(3)练习
接下来,让我们做个练习,模仿登录知乎,下面是示例代码:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
service = Service(r"D:\chromedriver\chromedriver.exe")
driver = webdriver.Chrome(service=service)
driver.get("https://www.zhihu.com/signin?next=%2F")#切换到密码登录
qie_huan = driver.find_elements(by=By.CLASS_NAME, value="SignFlow-tab")[1]
qie_huan.click()# 输入账号
username = driver.find_element(by=By.NAME, value="username")
username.send_keys("123456789")# 输入密码
password = driver.find_element(by=By.NAME, value="password")
password.send_keys("abc123456789")# 点击登录
submit = driver.find_element(by=By.CLASS_NAME, value="SignFlow-submitButton")
submit.click()
5. selenium的行为链
(1)行为链
有时候在页面中的操作可能要有很多步,那么这时候可以使用鼠标行为链类(selenium.webdriver.common.action_chains.ActionChains)来完成。
下面列举一些鼠标的相关操作:
- click_and_hold(element):点击但不松开鼠标
- context_click(element):右键点击
- double_click(element):双击 更多方法可以参考: https://selenium-python.readthedocs.io/api.html
(2)为什么需要行为链?
因为有些网站可能在游览器端做一些验证行为是否符合人类的行为来做反爬虫。这时候我们就可以使用行为链来模拟人的操作
(3)练习
用行为链模拟登录知乎
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
import time
service = Service(r"D:\chromedriver\chromedriver.exe")
driver = webdriver.Chrome(service=service)
driver.get("https://www.zhihu.com/signin?next=%2F")# 创建行为链
actions = ActionChains(driver)# 先进入密码登录方式
qie_huan = driver.find_elements(by=By.CLASS_NAME, value="SignFlow-tab")[1]
actions.move_to_element(qie_huan)
actions.click(qie_huan)
actions.perform()
time.sleep(1)# 延迟1秒,预防可能出现页面表单元素等未加载完成的情况# 获取输入框等表单元素
username = driver.find_element(by=By.NAME, value="username")
password = driver.find_element(by=By.NAME, value="password")
submit = driver.find_element(by=By.CLASS_NAME, value="SignFlow-submitButton")# 点击
actions.move_to_element(username)
actions.send_keys_to_element(username,"123456789")
actions.move_to_element(password)
actions.send_keys_to_element(password,"abc123456789")
actions.move_to_element(submit)
actions.click(submit)# 执行点击事件
actions.perform()
6. selenium操作cookie
(1)cookie操作
# 获取所有的cookiefor cookie in driver.get_cookie():print(cookie)# 根据cookie的key获取value
value = driver.get_cookie(key)# 删除所有的cookie
driver.delete_all_cookies()# 删除某个cookie
driver.delete_cookie(key)# 添加cookie
driver.add_cookie({"name":"username","value":"abc"})
7. 页面等待
现在的网页越来越多采用了ajax技术,这样程序便不能确定何时某个元素完全加载出来了,如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题,所以selenium提供了两种等待方式:显示等待和隐式等待
- 隐式等待:调用driver.implicitly_wait,那么在获取不可用元素之前,会先等待n秒时间,示例代码如下:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
service = Service('D:\chromedriver\chromedriver.exe')
driver = webdriver.Chrome(service=service)
driver.get("https://www.baidu.com/")
driver.implicitly_wait(5)
driver.find_element(by=By.ID, value="abcd")
- 显示等待:显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间就会抛出一个异常。显示等待应该使用selenium.webdriver.support.excepted_conditions期望的条件和selenium.webdriver.support.ui.WebDriveWait来配合完成,示例代码如下:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
service = Service('D:\chromedriver\chromedriver.exe')
driver = webdriver.Chrome(service=service)
driver.get("https://www.12306.cn/index/")
WebDriverWait(driver,100).until(
EC.text_to_be_present_in_element_value((By.ID,"fromStationText"),"北京"))
WebDriverWait(driver,100).until(
EC.text_to_be_present_in_element_value((By.ID,"toStationText"),"上海"))
btn = driver.find_element(by=By.ID, value="search_one")
btn.click()
8. 打开和切换窗口
(1)页面切换
有时候窗口有很多子tab页面,这时候肯定是需要进行切换的,selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到,示例代码如下:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
service = Service('D:\chromedriver\chromedriver.exe')
driver = webdriver.Chrome(service=service)
driver.get('https://www.baidu.com/')# selenium中没有专门的打开新窗口的方法,是通过"window.execute_script()"来执行’is‘脚本的形式来打开新窗口的
driver.execute_script("window.open('https://www.douban.com/')")# 切换页面(打开新窗口后’driver‘当前的页面依然还是之前的页面,如果想获取新窗口的源代码,必须切换页面)
driver.switch_to.window(driver.window_handles[1])# 获取当前页面的源代码print(driver.page_source)
9. 设置代理IP
有时候频繁爬取一些网页,服务器发现你是爬虫后会封掉你的ip地址,这时候我们可以更改代理IP,更改代理ip不同的游览器有不同的实现方式,这里以chrome游览器为例:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://101.34.214.152:8001")
service = Service('D:\chromedriver\chromedriver.exe')
driver = webdriver.Chrome(service=service, chrome_options=options)
driver.get('http://httpbin.org/ip')
大家可以去快代理获取免费的IP来练习,不过快代理IP因为是免费的原因所以不太稳定,有可能出现不稳定的情况,大家可以多试几个IP
三. 补充及小结
(1)webelement.get_property:获取html的官方属性对应的值
(2)webelement.get_attribute:获取这个标签的某个属性(包含自定义属性)的值
(3)driver.screenshot:获取当前页面的截图,这个方法只能在driver上使用
本篇的内容差不多到这里就结束了,相信大家对于动态爬虫和selenium模块等有一定的了解了,基本的知识本篇内容基本都有介绍到,如果不懂的可以进行反复观看和练习,如果大家想进一步学习,大家可以通过查看各类、各模块的源代码来进行理解练习噢!
看到这里了,可以留下你的点赞和收藏吗~
版权归原作者 梓梓子chen 所有, 如有侵权,请联系我们删除。