4、selenium模块基础

爬虫快速入门 / 2021-06-02

一、selenium基础

官网地址:https://www.selenium.dev/

1.1、什么是selenium?

摘自官网文档开头第一段话:

Selenium is an umbrella project for a range of tools and libraries that enable and support the automation of web browsers.

It provides extensions to emulate user interaction with browsers, a distribution server for scaling browser allocation, and the infrastructure for implementations of the W3C WebDriver specification that lets you write interchangeable code for all major web browsers.

对于我们本次学习来说,selenium是基于浏览器自动化的模块,用代码来模拟像人类一样操作浏览器。

selenium:所见即可爬!

1.2、为什么用它?

在上一次爬虫学习中,我们尝试了爬取网站的视频,其实这是我找了好几个网站中最简单的。我们爬虫过程中经常会遇到动态加载的数据,我们需要手动捕获数据包去分析是否动态加载然后重新发起请求,各种网站的反爬措施层出不穷,我们直接用requests模块取爬取数据,极其费劲还容易被拒绝访问。

这个selenium库可以模拟人类手动操作浏览器,从而规避了很多网站的检测,提高了爬虫程序的隐蔽性和可用性。selenium支持众多浏览器、众多平台和语言,这点非常棒!

1.3、如何使用它?

安装库、驱动,实例化浏览器对象三步走。

安装库

安装selenium模块,并下载安装对应的浏览器驱动,注意两者映射关系

pip install selenium
安装浏览器驱动

跟显卡一样,每一款浏览器每一个版本都对应着不同的驱动程序,这里以Google chrome浏览器为例,这是官网对应的谷歌驱动下载链接:https://sites.google.com/a/chromium.org/chromedriver/downloads

实例化浏览器对象

首先生成一个浏览器对象,此处因为我使用的是Deepin系统,执行后提示找不到cannot find Chrome binary,所以我需要手动指定浏览器的目录。

执行后,浏览器会自动弹出且提示当前浏览器被自动测试软件所控制。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options


option = Options()
option.binary_location = '/usr/bin/google-chrome-stable'
brower = webdriver.Chrome(executable_path='./chromedriver', chrome_options=option)

二、selenium常用方法

更详细的方法请参阅文首给定的官方文档,这里罗列较为常见的一些方法。

2.1、get请求

在之前我们试图爬取国家食品药品监督总局数据时,发现它页面数据部分是动态加载的,这给我们的爬取造成了一定的麻烦,而这次,selenium能给我们带来惊喜吗?

get(),类似requests.get(),向一个URL发起GET请求。

url = 'https://mirrors.tuna.tsinghua.edu.cn'
option = Options()
option.binary_location = '/usr/bin/google-chrome-stable'
brower = webdriver.Chrome(executable_path='./chromedriver', chrome_options=option)
brower.get(url=url)

2.2、获取页面源码

page_source方法可以获取页面源码数据

brower.page_source

2.3、标签查找

selenium提供了很多种方式来查找定位标签,不需要记,因为方法的名称足够见名知意,需要时输入find即可。

brower.find_element_by_xpath('//*[@id="mirror-list"]/table/tbody/tr[55]/td[1]/a')
brower.find_elements_by_name('author')
brower.find_element_by_id('author')

2.4、标签交互

很多时候我们需要在页面上输入账号密码,这个事情selenium也能干,这需要用到send_keys()方法。

input_tag = brower.find_element_by_id('search')  # 首先进行标签定位
input_tag.send_keys('deepin')  # 标签交互,发送文本内容。

2.5、执行JavaScript代码

selenium还可以模拟鼠标滚动,比如屏幕往下滚一屏,需要用到execute_script()方法执行JavaScript代码。

brower.execute_script('window.scrollTo(0, document.body.scrollHeight)')

2.6、点击按钮

先进行标签定位,然后执行点击。

search_btn = brower.find_element_by_class_name('btn-search')
search_btn.click()

2.7、前进后退

brower.back()
brower.forward()

2.8、动作链SctionChians

如果想要的标签被包含在一个iframe子页面中,直接用标签定位会报错找不到,得先调用switch_to.frame('标签'),切换浏览器标签定位的作用域,再定位标签。

使用动作链需要先生成动作链对象

from selenium.webdriver import ActionChains


action = ActionChains(brower)
2.8.1、切换窗口

切换到另一个窗口

brower.switch_to_window("windowName")
2.8.2、切换iframe页面

切换到当前页面镶嵌的子页面(iframe)

brower.switch_to_frame("frameName")
2.8.3、按住鼠标

模拟人类点击并按住鼠标的操作

action.click_and_hold('指定标签')
2.8.4、拖动鼠标

拖动十次,每次拖动鼠标水平方向向右移动17像素,perform是执行链条所有操作。

for num in range(10):
    action.move_by_offset(17, 0).perform()
2.8.5、释放动作链

执行完动作,要释放动作链,就跟open打开一个文件要调用close一样。

action.release()

2.9、退出浏览器

brower.quit()

2.10、模拟登录

这次来模拟登录深度科技论坛

url = 'https://login.deepinid.deepin.com/oauth2/authorize?access_type=offline&client_id=6b19a7fd09783519f0c8d79a6a5c1d57e7853871&redirect_uri=https%3A%2F%2Fbbs.deepin.org%2Fapi%2Fv1%2Flogin%2Fcallback&response_type=code&scope=base%2Cuser%3Aread%2Cuser%3Acontact%3Aread&state=a1f800a3a08c80ecf50447c57595c46b'
brower.get(url)

input_username = brower.find_element_by_id('username')
input_passwd = brower.find_element_by_id('password')
input_username.send_keys('账号')
sleep(1)  # 模拟延迟,也可以不要,直接输入然后登录。
input_passwd.send_keys('密码')
sleep(1)
brower.find_element_by_id('submit_bt').click()

2.11、无可视化界面

有时候出于某些目的,我们可能不希望让窗口弹出来,能不能让浏览器悄悄地执行?有的,可以叫它:无可视化界面,还有个phantomJs(已停止维护)也可以做到这个效果。

凡是要给浏览器添加参数,都需要实例化产生Options对象,因为是无可视化界面,为了证明确实在后台运行过,我们可以打印一下页面源码。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options


option = Options()
option.binary_location = '/usr/bin/google-chrome-stable'
option.add_argument('--headless')
option.add_argument('--disable-gpu')
brower = webdriver.Chrome(executable_path='./chromedriver', chrome_options=option)

url = 'https://www.baidu.com'
brower.get(url)

page_source = brower.page_source
print(page_source)

2.12、开发者模式

爬虫与反爬虫技术都在不断地增长,有可能网站还会检测请求是否是selenium的请求,是则会被拒绝,能不能稍微规避一下下?

上面我们都是用from selenium.webdriver.chrome.options import Options,以后就用ChromeOptions好了。

option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
brower = webdriver.Chrome(executable_path='./chromedriver', chrome_options=option)

三、12306模拟登录

selenium无法实现识别验证码功能,需要借助第三方工具识别,这种在图片中选择的验证码比英文数字验证码难多了。

还是用百度云不用超级鹰

原理就是利用第三方API识别图片得到小图片坐标,接着利用selenium

这里有个情况,不能单独对验证码图片发起请求,因为一发起网络请求就是随机刷新另一张,如何获取?

selenium先打开网页,直接截图然后截取验证码部分,这靠谱吗?

brower.find_element_by_xpath('/html/body/div[2]/div[2]/ul/li[2]/a').click()
brower.save_screenshot('img.png')

可以,截图后需要确定验证码图片对应的而左上角和右下角坐标,这是裁剪区域

先定位标签,然后使用location获取左上角坐标,size是标签对应的长宽

tag = brower.find_element_by_id('J-loginImg')
tag_location = tag.location
tag_size = tag.size
coordinate = (
    tag_location.get('x'), tag_location.get('y'), tag_location.get('x') + tag_size.get('width'),
    tag_location.get('y') + tag_size.get('height')
)

交给云端识别验证码

使用selenium进行坐标点击

先处理好坐标数据,selenium要切换到标签所对应的坐标再点击

未完待续

世间微尘里 独爱茶酒中