一、selenium基础
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要切换到标签所对应的坐标再点击
未完待续