python网络爬虫 五
Selenium
selenium介绍与安装
当网页使用JavaScript动态加载时,我们的requests和Beautiful Soup似乎就失去了它们神奇的能力,这时我们就需要selenium来帮助我们爬取网页
selenium 是一款功能强大的网络爬取工具,最初是为网站测试自动化而开发的。selenium通过浏览器来自动加载网站,检索其内容以及执行用户在使用浏览器时所采取的操作。因此,它也是一种强大的网络爬取工具
与requests库和beautiful soup库的安装一样,我们只需要在python的目录文件中打开cmd输出一下内容即可:
pip install -U selenium
我们还需要下载一个webdriver来配合selenium的使用
可以前往https://sites.google.com/a/chromium.org/chromedriver/downloads
并下载与你操作系统匹配的最新版本
如果有的同学无法访问这个网站(可能需要翻墙),我们可以去这个镜像网站找到对应版本
http://npm.taobao.org/mirrors/chromedriver/
一定要是匹配版本!!!可以通过chrome浏览器的设置中查看自己浏览器的版本
(我自己以前下载的chromedriver刚刚运行一下都出现了版本不匹配的错误报告)
还有就是下载好的chromedriver直接放在python.exe同一个文件夹中确保正确运行
当这些都完成之后,我们可以通过一个简单的例子测试一下:
from selenium import webdriver
url = 'https://www.baidu.com'
driver = webdriver.Chrome()
driver.get(url)
input('press enter to close the automated browser')
driver.quit()
运行后等待几秒,我们就可以看到会自动加载一个页面
chrome浏览器会告诉你,浏览器正在受到自动测试软件的控制(贴心)
下面我们可以开始我们的爬取了
使用selenium爬取网页
find_element_by_方法简介
加载好页面之后,我们希望能够获取HTML元素,使用的方法和“美丽汤”略有不同,但是理解起来并不太难,而且这些方法都会返回元素列表
find_element_by_id
find_element_by_name
# 根据HTML的‘name’属性选择元素
find_element_by_xpath
find_element_by_partial_link_text
# 匹配其部分内部文本来选择元素
find_element_by_link_text
# 匹配内部文本来选择元素
find_element_by_tag_name
# 使用实际的标签名称选择元素
find_element_by_class_name
find_element_by_css_selector
xpath表达式
这里简单的介绍下xpath的表达式
nodename 选择名为 ‘nodename’ 的所有结点
/ 从根节点中选择
// 用于跳过多级结点并搜索所有后代以执行选择
. 选择当前结点
.. 选择当前结点的父节点
@ 选择属性
* 表示匹配任何元素结点
当然我们前面提过,chrome浏览器直接提供copy xpath和css表达式的方法,我们可以直接复制粘贴哟!!!
对新手太友好了!!!
当然我们可以稍微解释一下,是如何得到这个表达式的,比如我们要获取这行HTML的信息,我们的xpath表达式是这样的:
//*[@id="s-top-left"]/a[1]
//表示匹配后面所有的结点
* 选择所有的元素结点
选择属性id='s-top-left'的结点
/ 从该结点选择
a[1] 第一个a中的内容
具体的xpath完整的学习可以参考这个网站
https://www.runoob.com/xpath/xpath-tutorial.html
一个超棒的学习网站!!!
隐式与显式等待
我们可以注意到,我们运行代码到chrome浏览器打开是需要一定时间的,如果我们还没有等JavaScript内容加载出来就开始我们的爬取,那么我们很可能出错。所以我们应该适当的让代码停顿一下再往下执行,所以我们使用selenium提供的两种类型的等待:隐式等待和显式等待
隐式等待
每次尝试定位元素时,隐式等待都会使webdriver轮询页面一段时间。所以可以把隐式等待视为预设条件,每次尝试定位元素时,我们都会等待指定的时间,所以我们可以这样写代码:
from selenium import webdriver
url = 'https://www.baidu.com'
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 设置隐式等待10s
driver.get(url)
for i in driver.find_elements_by_xpath('//*[@id="s-top-left"]/a'):
print(i.text)
driver.quit()
那么我们就可以得到下面的结果:
新闻
hao123
地图
视频
贴吧
学术
也十分方便不是吗
显式等待
显式等待能够提供更精细的控制。显式等待使webdriver等待某个给定的条件并返回非False值,然后继续执行,这种情况一直重复,知道它返回一些内容或者超出给定的时间。
我们想要完成显式等待,我需要一下导入
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
EC提供了大量的内置条件,因此我们不需要自己编写代码,这里只列出来几个常用的
alert_is_present: 检查是否存在警报
new_window_is _opened(current_handles): 检查是否已经打开新窗口
presence_of_all_elements_located(locator):
检查页面上是否存在与locator匹配的至少一个元素,找到则返回第一个匹配元素
title_contains(title): 检查页面标题是否包含给定字符串
url_changes(url): 检查url是否与给定的相同
还有很多,想要跟多了解的可以查看selenium文档哟
给出一段代码来展示显式等待是如何工作的:
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
url = 'https://www.baidu.com'
driver = webdriver.Chrome()
driver.implicitly_wait(10) # 设置隐式等待
driver.get(url)
'''for i in driver.find_elements_by_xpath('//*[@id="s-top-left"]/a'):
print(i.text)'''
re = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located(
(By.ID, "s-top-left")
)
)
# 工作原理:使用webdriver创建一个对象,并且给定等待的秒数,然后调用
# until方法,提供一个条件对象,我们使用上面提到的presence_of_all_elements_located
# 参数是一个包含两个元素的元组,第一个元素根据选择元素的方法定,第二个参数给出实际值
# 反复检查此条件,直到十秒过去,或者条件返回非false内容
# 这里新加载的By类就是专门提供我们构造方法的类
for i in re:
print(i.text)
driver.quit()
输出结果:
新闻hao123地图视频贴吧学术更多
更多selenium技巧
- 我们每次使用**find_element_by_* 或者 find_elements_by_***方法检索元素时,selenium会返回WebElement对象,selenium还提供访问这些对象的方法:
!!!我们可以在WebElement对象上再次使用
find_element_by_* 或者 find_elements_by_等检索方法
来从当前元素开始新的元素搜索
使用click方法单击元素
如果时文本输入元素,使用clear可以清除该元素的文本
get_attribute 方法获取HTML属性或者元素的属性
如‘element.get_attribute('herf)’
get_preperty 方法获取元素的属性
send_keys 方法模拟键入元素
submit 方法提交表单
text 返回元素的文本
- selenium还提供一个ActionChains对象来构建更精细的操作链,比如悬停和拖放。他们通过构建一个驱动对象来构建,包含以下方法:
click(on_element = None) : 单击元素。给定None则使用鼠标的当前位置
click_and_hold() : 在元素上或当前鼠标位置按住鼠标左键
context_click() : 对元素或者鼠标当前位置执行右击操作
double_click() : 双击元素或者当前鼠标的位置
drag_and_drop(source, target) : 按住source上的鼠标左键,
然后移动到target上并释放鼠标按钮
send_keys_to_element(element, *keys_to_send) : 将健发送到元素
pause(seconds): 给定等待的秒数
perform() : 执行在操作链上定义的所有操作
reset_actions() : 清除存储在远程端上的操作
实战:在百度上自动搜索内容代码
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
url = 'https://www.baidu.com'
driver = webdriver.Chrome() # 创建对象
driver.implicitly_wait(10) # 设置隐式等待
driver.get(url)
tar = driver.find_element_by_xpath('//*[@id="kw"]') # 找到输入框
tar.click() # 单击
cont = input("请输入你想要查询的内容:\n")
tar.send_keys(str(cont)) # 将内容发送到输入框
tar.send_keys(Keys.ENTER) # 回车进行搜索
input("Press enter to close the automated browser:\n")
driver.quit()
当然还可以添加后续代码进行更多的拓展哟!
赶紧实战起来吧!
点个赞呗!(卑微)