Ajax形式的请求时JS动态渲染的一种手段,我们可以通过requests和urllib库来实现页面数据抓取,但是js动态渲染页面不仅仅是AJAX一种形式,
有的网页是由JS直接生成的,并非原始HTML,可能还不包含AJAX请求;例如一些报表工具ECharts 官网的实例,图形都是通过JS生成的;例如淘宝页面,即使是AJAX请求数据,但是接口中包含了很多加密参数,我们很难以找到规则,也因此很难分析AJAX请求来抓取数据;
为了解决以上问题,我们可以直接通过使用模拟浏览器运行的方式实现,那么就可以实现原本浏览器中可以看到的,抓取的数据就是什么样,即所见即所"得"(爬);此时我们不用再去关心网页中JS使用了什么算法或者结构实现了页面渲染,不用关心网页后台的AJAX接口到底有哪些参数;
Python提供了好多模拟浏览器运行的库,例如:Seleium,Splash,PyV8,Ghost等;
Selenium的使用
Selenium是一个自动化测试工具,可以按照指定的命令自动操作;
安装: pip install selenium
官网:http://www.seleniumhq.org
中文文档:http://selenium-python-zh.readthedocs.io
例如火狐浏览器如下安装方式:
下载解压后,将chromedriver.exe , geckodriver.exe , Iedriver.exe发到Python的安装目录,例如 D:\python 。这里我们只用了火狐浏览器为例,
则将 geckodriver.exe 放入python根目录;然后再将Python的安装目录添加到系统环境变量的Path下即可;
这里我放在了:D:\Programs\Python\Python37\Scripts目录,且之前已经在Path下设置了该目录的环境变量;
测试是否安装成功,如果执行后打开一个对应浏览器的空白页,则表示安装成功;
火狐浏览器启动:
1 from selenium import webdriver
2 browser = webdriver. Firefox()
谷歌浏览器启动:
1 from selenium import webdriver
2
3 browser = webdriver.Chrome()
IE浏览器启动:
1 from selenium import webdriver
2
3 browser = webdriver.Ie()
注:此方法有不便之处,即在程序运行过程中需要一直开着浏览器,在爬取网页过程中浏览器可能一直开启,目前Chrome浏览器版本已经支持无界面模式了,如果版本比较旧此时就不会支持无界面模式;
还有另一种方式,即安装一个无界面浏览器PhantomJS,此时抓取过程都会在后台运行,不会再弹出浏览器窗口了;
1.浏览器对象声明:
Selenium支持非常多的浏览器,例如Chrome、Firefox、Edge等,还有Android,BlackBerry等手机端的浏览器;也支持无界面的PhantomJS;
例如:
from selenium import webdriver
browser = webdri ver. Chrome()
browser = webdriver. Firefox()
browser = webdri ver. Edge()
browser = webdriver. PhantomJS()
browser= webdriver.Safari()
2.浏览器对象访问资源
可以通过get()方法请求页面,参数传入连接URL即可;
1 from selenium import webdriver
2 browser = webdriver. Firefox()
3 browser.get('https://www.baidu.com')
4 print(browser.page_source)
5 browser.close()
3、查找节点
Selenium可以驱动浏览器完成各种操作,例如:填充表单,模拟单击事件等;
比如我们想通过程序添加表单数据,需要知道保单在那个位置;但是Selenium提供了一系列查找节点的方法,我们可以利用这些方法获取节点,做下一步执行动作和信息抓取做准备;
例如:
1 from selenium import webdriver
2 browser = webdriver. Firefox()
3 browser.get('https://www.baidu.com')
4 input_1=browser.find_element_by_id('kw')#百度输入框的id为kw
5 input_2=browser.find_element_by_css_selector('#kw')#按照css选择器选择对象
6 input_3=browser.find_element_by_xpath('//*[@id="kw"]')#按照xml path选择元素
7
8
9 print(input_1)
10 print(input_2)
11 print(input_3)
12 browser.close()
find_element()方法:
该方法有两个参数,表示查找方式by和值;即:find_element_by_id('id值') 等价find_element(By.ID,'id值')
是一种通用的查找方法;
find_elements()方法:
该方法用于多个节点的查找,比上面方法多了个s字母,
例如:
browser.find_elements_by_class_name
browser.find_element_by_class_name
两个方法,一个带s一个不带,则前者是查找多个节点,后者只找一个节点;
1 news_menus1=browser.find_elements(By.CSS_SELECTOR,'.mnav')
2 news_menus2=browser.find_elements(By.CLASS_NAME,'mnav')
4、节点交互
Selenium 可以驱动浏览器来执行一些动作,即让浏览器模拟执行一些动作;常见用法:
输入文字时用send_keys()方法,清空文字则使用clear()方法,点击按钮则click()方法;
例如:先输入Python关键词,然后清空,在输入JAVA,点击按钮访问;此时为了看到更好效果,则加入休眠5秒;
1 from selenium import webdriver
2 import time
3 from selenium.webdriver.common.by import By
4 browser = webdriver. Firefox()
5 browser.get('https://www.baidu.com')
6 input_1=browser.find_element_by_id('kw')#百度输入框的id为kw
7 input_1.send_keys('Python')
8 time.sleep(5)
9 input_1.clear()
10 input_1.send_keys('JAVA')
11 time.sleep(5)
12 suBtn=browser.find_element_by_id('su')
13 suBtn.click()
14
15 browser.close()
5、动作链
上面实例是通过点击触发的事件,例如鼠标拖拽,键盘按键灯,这些动作需要通过另一种方式执行,即所谓的动作链;
鼠标事件:
事件 | 描述 |
context_click() | 鼠标右击 |
double_click() | 鼠标双击 |
drag_and_drop(source,target) | 拖动 |
move_to_element() | 光标悬停 |
move_to | 移动 |
键盘事件:
事件 | 描述 |
send_keys(Keys.BACK_SPACE) | 删除按键 |
send_keys(Keys.SPACE) | 空格键 |
send_keys(Keys.TAB) | Tab键 |
send_keys(Keys.ESCAPE) | ESC键 |
send_keys(Keys.ENTER) | 回车键 |
send_keys(Keys.CONTROL,'a') | A |
send_keys(Keys.CONTROL,'c') | C |
send_keys(Keys.CONTROL,'x') | X |
send_keys(Keys.CONTROL,'v') | V |
... | ... |
send_keys(Keys.F1) | F1 |
send_keys(Keys.F5) | F5 |
send_keys(Keys.F12) | F12 |
... | ... |
例如: