对于ajks请求,确认好接口可以直接完成数据的爬取,只要找到接口的参数构造其规律就可以循环生成一个请求。如果这个接口有加密的参数,是不能直接模拟ajks请求的。此时解决方法同样有俩种:
1深挖逻辑,找到js加密的参数逻辑,用python代码生成加密的参数来构造ajks,简称js逆向
2模拟浏览器来爬取,利用浏览器驱动的动作,获取当前呈现的页面源码
1准备工作,安装Chrome浏览器 并配置对应版本的浏览器驱动ChromeDriver,官网可下载。
浏览器地址栏输入 chrome://version/
浏览器驱动官网下载地址 :http://chromedriver.storage.googleapis.com/index.html
下载好放到谷歌浏览器安装的同一文件夹下即可
2声明浏览器对象
from selenium.webdriver.common.by import By
from selenium import webdriver
url = 'http://www.baidu.com'
browser = webdriver.Chrome() #指定谷歌浏览器,通过browser对象可以模拟浏览器操作
3访问页面
browser.get(url) #声明浏览器打开指定的url
print(browser.page_source) #打开url 输出当前页面的源码
browser.close() #关掉浏览器
4查找单个节点
find_element_by_id
find_element_by_name
find_element_by_xpath
find_element_by_link_text
find_element_by_tag_name
find_element_by_class_name
以上是常用的查找单个节点的方法 直接调用即可,节点的对象类型都是webElement类型,使用方法如下
id = browser.find_element_by_id('image_list') #定位id名字为image_list节点并返回一个webElement对象
或者 browser.find_element(By.ID,'image_list') #结果是一样的
5查找多个节点
唯一区别 element多个s,代码如下:
title = browser.find_elements(By.name,'title')
#定位到所有name属性为title的所有节点的列表的一个webElement对象的集合。
6节点交互
kw = browser.find_element(By.ID,'kw') #定位到kw节点 输入框的id
kw.clear() #清空这个输入节点的内容
kw.send('python') #这个节点输入内容 python
kw.click() #触发kw的点击事件
.
7执行javascript
selenium并没有实现某些操作方法,但可以去执行js代码来模拟运行下拉条进度直接用execute_script方法即可
browser.get(url)
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')#下拉到最底部
browser.execute_script('alert("To Bottom")')#执行js代码 弹框
8获取节点信息 (获取属性)
首先定位到具体的某个节点
browser.get(url)
kw = browser.find_element(By.ID,'kw') #定位到id为kw的节点,返回一个webelement对象
print(logo.get_get_attribute('name')) #获取id为qw的节点的name属性
通过调用节点的get_get_attribute()方法 里面传入这个节点内含有的key名字 即可
9获取文本值
browser.get(url)
kw = browser.find_element(By.ID,'kw') #定位id为kw的节点,
print(kw.text) #直接调用text方法获取文本值
10 获取 ID ,位置,标签名,大小
browser.get(url)
kw = browser.find_element(By.ID,'kw') #定位到id为kw的节点
print(kw.id) #获取当前节点的 id信息
print(kw.location) #获取当前节点的 相对位置信息
print(kw.size) #获取当前节点的 大小,宽度信息
print(kw.tag_name) #获取当前节点的标签名字
11切换Frame Selenium默认是父级别页面操作,如果还有子页面中含有数据,Selenium是无法获取子页面的节点的,这时候就需要switch_to.frame方法来切换下子节点,代码如下:
from selenium.common.exceptions import NoSuchElementException
browser.get(url)
ifra = browser.switch_to.frname('iframeResult') #切换到子页面
try:
kw = ifra.find_element(By.ID,'kw') #定位子页面中的 id为kw的节点
except NoSuchElementException :
pirnt('没有当前子节点')
browser.switch_to.parent_frame() #在切换到父级的页面
首先通过switch_to.frname切换到子页面,然后尝试获取kw节点,如果不存在就抛出异常,捕获后
输出没有当前子节点, 然后切换到对应的Franme,再进行操作
12 延时等待
隐士等待:固定一个时间,超出时间就报错
显示等待:指定要查找的节点,然后指定最长的一个等待时间,在规定时间内加载成功就返回这个节点;在规定时间内没有加载出来这个节点,就会报错,代码如下:
from selenium improt webdriver
from selenium.webdriver.commob.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Chrome()
browser.get('https://www.jd.com')
wait = WebDriverWait(browser,10) #引入WebDriverWait模块指定最长等待时间,
input = wait.until(EC.presence_of_element_located((By.ID,'q')))
#wait的对象调用until方法,需要传入要等待的条件,比如传入EC.presence_of_element_located()
定位到id为q的节点加载出现,10秒内加载出来就返回节点对象,返回不出来就抛出异常
button = wait.until(EC.element_to_be_clickable((By.ID,'btn')))
print(input,button)
更多详细的等待条件的参数及用法介绍可以参考官方文档:http://selenium-python.readthedocs.io/api.html#module-selenium.webdriver.support.expected_conditions。
13前进后退
browser.get(url)
browser.back() #后退一个页面
browser.forward() #前进一个页面
#一般多用于连续访问
14操作Cookies 获取,添加,删除等
browser .get(url)
browser.get_cookies() #获取cookies值
browser.add_cookies({XXX}) #自定义添加cookies值,字典的形式传入
browser.delete_all_cookies() #删除所有的cookies
15异常处理
在使用selenium解析网页 经常会遇到超时或者节点未找到错误,程序便会终止运行,所以需要try except 捕获处理,t
from selenium.common.exceptions import TimeOutException,NoSuchElementException
browser .get(url)
try:
kw = browser.find_element(By.ID,'hello')
except NoSuchElementException:
print('No Find Element!')
关键点引入俩个模块,分别是TimeOutException,NoSuchElementException,针对不同的情况分别是捕获处理,保持程序不会中断
16 反屏蔽
部分网站会有Selenium检测,来进行反爬虫。多数情况下检测基本原理是检测当前浏览器窗口下的 window.navigator 对象是否包含 webdriver 这个属性。正常情况下是unfined,如果js判断这个属性webdriver的存在,就会直接屏蔽,
from selenium import webdriver
from selenium.webdriver import ChromeOptions #引入Chrome开发工具协议
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option('useAutomationExtension', False)
browser = webdriver.Chrome(options=option)
browser.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': 'Object.defineProperty(navigator, "webdriver", {get: () => undefined})'
}) #每次页面加载之前将 webdriver 属性置空
browser.get('https://www.baidu.com/')
17无头模式
Selenium会弹出浏览器 多次会形成干扰,同时为减少一些资源加载,可以设置为无头模式,节省资源加载的时间和宽带资源,借助于Chrome开发工具协议开启无头模式,如下:
from selenium.webdriver improt ChromeOptions #引入Chrome开发工具协议
from selenium import webdirver
options = ChromeOptions() #实例化Chrome开发工具对象
options.add_argument('--headless') #调用.add_argument('--headless')方法
browser = webdirver.Chrome(options=options) #声明谷歌浏览器,并传入开发工具设置的环境
browser.set_windows_size(1366,768) #设置窗口的大小
browser.get(url) #打开指定网址
browser.get_screenshot_as_file('preview.png') #输出截图
通过 ChromeOptions 的 add_argument 方法添加了一个参数 --headless,开启了无头模式。在无头模式下,最好需要设置下窗口大小,接着打开页面,最后调用 get_screenshot_as_file 方法输出了页面的截图。