Python网络爬虫 第六章 自动化
一、selenium引入概述
我们在抓取⼀些普通⽹⻚的时候requests基本上是可以满⾜的,但是,如果遇到⼀些特殊的⽹站,它的数据是经过加密的,但是浏览器却能够正常显示出来。那我们通过requests抓取到的内容可能就不是我们想要的结果了。 例如,电影票房数据,在浏览器上看的时候是正常的。那么按照之前的逻辑,我们只需要看看数据是通过哪个请求拿到的就可以进⾏模拟请求了。
但是!
简单介绍⼀下selenium, 它本身是⼀个⾃动化测试的⼯具. 可以启动⼀个全新的浏览器.并从浏览器中提取到你想要的内容. 随着各种⽹站的反爬机制的出现. selenium越来越受到各位爬sir的喜爱.
selenium最⼤的缺点其实就⼀个, 慢! 你想啊. 他要启动⼀个第三⽅的软件(浏览器), 并且还要等待浏览器把数据渲染完毕. 这个过程必然是很耗时的. 所以它慢.
接下来, 我们来聊聊selenium如何安装和使⽤.
就像其他第三⽅库⼀样, selenium直接⽤pip就可以安装了
pip install selenium
但是呢, 它与其他库不同的地⽅是他要启动你电脑上的浏览器, 这就需要⼀个驱动程序来辅助.
chrome驱动地址:https://npm.taobao.org/mirrors/chromedriver
这⾥推荐⽤chrome浏览器. 其他浏览器的驱动请⾃⾏百度.
我这里是windows系统就选择win32
然后关键的来了. 把你下载的浏览器驱动放在程序所在的⽂件夹. 或者放到python解释器所在的⽂件夹. 两种⼆选其⼀.
python解释器的文件夹在Console上便能看到
OK~ 前期准备⼯作完毕. 上代码看看, selenium是个什么⻤
# 让selenium启动谷歌浏览器 from selenium.webdriver import Chrome # 1.创建浏览器对象 web = Chrome() # 2.打开一个网址 web.get("http://www.baidu.com") print(web.title)
运⾏⼀下你会发现神奇的事情发⽣了. 浏览器⾃动打开了. 并且输⼊了⽹址. 也能拿到⽹⻚上的title标题.
二、selenium各种神奇操作
selenium不但可以打开浏览器. 还可以对浏览器各种操作. ⽐如, 点 击, 查找. 都可以.
我们直接上案例. 抓取拉钩⽹招聘python⼯程师的招聘信息
1、准备⼯作
2、点击-全国按钮
想要点击这个按钮. 我们需要先定位到这个按钮. 然后再点击selenium想要定位某个元素. 太简单了.
web = Chrome() web.get("http://lagou.com") # 找到某个元素. 点击它 el = web.find_element_by_xpath('//*[@id="changeCityBox"]/ul/li[1]/a') el.click() # 点击事件
3、搜索python
⼈的过程: 找到⽂本框输⼊"python", 点击"搜索"按钮.
机器的过程: 找到⽂本框输⼊"python", 点击"搜索"按钮.
发现没, ⽤selenium最爽的地⽅就是这⾥. ⼈是怎么操作的. 机器就怎么操作.
web.find_element_by_xpath('//*[@id="search_input"]').send_keys("python") web.find_element_by_xpath('//*[@id="search_button"]').click()
send_keys() 这⾥要说⼀下. 如果我们给出的是⼀个字符串. 就是输⼊⽂本. 但是, 如果给出的是⼀个键盘指令, 那就按下键盘. ⽐ 如, 我想要按回⻋按钮. 就是这样的
# 找到输入框. 输入python => 输入回车/点击搜索按钮 web.find_element_by_xpath('//*[@id="search_input"]').send_keys("python", Keys.ENTER)
4、提取招聘信息
from selenium.webdriver import Chrome from selenium.webdriver.common.keys import Keys # 键盘指令 import time web = Chrome() web.get("http://lagou.com") # 找到某个元素. 点击它 el = web.find_element_by_xpath('//*[@id="changeCityBox"]/ul/li[1]/a') el.click() # 点击事件 time.sleep(1) # 让浏览器缓一会儿 等ajax数据加载 # 找到输入框. 输入python => 输入回车/点击搜索按钮 web.find_element_by_xpath('//*[@id="search_input"]').send_keys("python", Keys.ENTER) time.sleep(1) # 查找存放数据的位置. 进行数据提取 # 找到页面中存放数据的所有的li li_list = web.find_elements_by_xpath('//*[@id="s_position_list"]/ul/li') for li in li_list: job_name = li.find_element_by_tag_name("h3").text job_price = li.find_element_by_xpath("./div[1]/div[1]/div[2]/div/span").text company_name = li.find_element_by_xpath('./div[1]/div[2]/div/a').text print(company_name, job_name, job_price) # 自动屏蔽掉了一些js加密解密问题,轻松多了
5、多窗口调度
上面说到我们已经可以通过selenium拿到拉钩⽹的招聘信息了. 但是, 信息不够全⾯. 我们希望得到的不仅仅是⼀个岗位名称和公司名称, 我更想知道更加详细的职位描述以及岗位要求
此时问题就来了. 我们可以在搜索⻚⾯点击进⼊到这个详情⻚. 然后就可以看到想要的职位描述了. 但是, 这时就涉及到如何从⼀个窗⼝转向另⼀个窗⼝了(切换选项卡).
⾸先, 我们先通过selenium定位到搜索⻚上的职位超链接
from selenium.webdriver import Chrome from selenium.webdriver.common.keys import Keys import time web = Chrome() web.get("http://lagou.com") web.find_element_by_xpath('//*[@id="cboxClose"]').click() time.sleep(1) web.find_element_by_xpath('//*[@id="search_input"]').send_keys("python", Keys.ENTER) time.sleep(1)
web.find_element_by_xpath('//*[@id="s_position_list"]/ul/li[1]/div[1]/div[1]/div[1]/a/h3').click()
注意! 我们看到的是新窗⼝的内容, 但是在selenium的视⻆⾥, 窗⼝依然停留在刚才那个窗⼝. 此时, 必须要将窗⼝调整到最新的窗⼝上才可以
# 如何进入到进窗口中进行提取 # 注意, 在selenium的眼中. 新窗口默认是不切换过来的. -1最后一个窗口 web.switch_to.window(web.window_handles[-1]) # 在新窗口中提取内容 job_detail = web.find_element_by_xpath('//*[@id="job_detail"]/dd[2]/div').text print(job_detail)
6 、无头浏览器
我们已经基本了解了selenium的基本使⽤了. 但是呢, 不知各位有没有发现, 每次打开浏览器的时间都⽐较⻓. 这就⽐较耗时了. 我们写的是爬⾍程序. ⽬的是数据. 并不是想看⽹⻚. 那能不能让浏览器在后台跑呢? 答案是可以的,只需要配置好参数即可。
# 准备好参数配置 opt = Options() # 无头 opt.add_argument("--headless") # 不显示 让程序在后台运行 opt.add_argument("--disbale-gpu") web = Chrome(options=opt) # 把参数配置设置到浏览器中
直接上案例吧. 拿出最开始我们看到的那个⽹⻚. 抓取电影票房.
from selenium.webdriver import Chrome from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.select import Select import time # 准备好参数配置 opt = Options() # 无头 opt.add_argument("--headless") # 不显示 让程序在后台运行 opt.add_argument("--disbale-gpu") web = Chrome(options=opt) # 把参数配置设置到浏览器中 web.get("https://www.endata.com.cn/BoxOffice/BO/Year/index.html") time.sleep(2) # 定位到下拉列表 sel_el = web.find_element_by_xpath('//*[@id="OptionDate"]') # 对元素进行包装, 包装成下拉菜单 sel = Select(sel_el) # 让浏览器进行调整选项 for i in range(len(sel.options)): # i就是每一个下拉框选项的索引位置 sel.select_by_index(i) # 按照索引进行切换 time.sleep(2) table = web.find_element_by_xpath('//*[@id="TableList"]/table') print(table.text) # 打印所有文本信息 print("===================================") print("运行完毕. ") web.close() # 如何拿到页面代码Elements(经过数据加载以及js执行之后的结果的html内容) print(web.page_source)
三、超级鹰解决验证码
1、超级鹰介绍
某些网站需要登录,输入用户名、密码以及验证码。用户名和密码的注入并不是很难,对于验证码的识别,通常的做法是利用一些图像识别算法解决,但通用性不强,这时可以选择网上成熟的验证码破解工具。
这里选择超级鹰进行验证码破解,官网:https://www.chaojiying.com/
超级鹰注册登录后,会免费获得1000积分,充值1元获得1000积分,有着明确的价格体系。
2、软件ID
现在用户中心-软件ID上生成一个软件ID,软件ID用来识别自己编写的脚本。
3、Python Demo
下载python的开发文档https://www.chaojiying.com/api-14.html
这里对Demo进行说明
import requests from hashlib import md5 class Chaojiying_Client(object): def __init__(self, username, password, soft_id): self.username = username password = password.encode('utf8') self.password = md5(password).hexdigest() self.soft_id = soft_id self.base_params = { 'user': self.username, 'pass2': self.password, 'softid': self.soft_id, } self.headers = { 'Connection': 'Keep-Alive', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', } def PostPic(self, im, codetype): """ im: 图片字节 codetype: 题目类型 参考 http://www.chaojiying.com/price.html """ params = { 'codetype': codetype, } params.update(self.base_params) files = {'userfile': ('ccc.jpg', im)} r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) return r.json() def ReportError(self, im_id): """ im_id:报错题目的图片ID """ params = { 'id': im_id, } params.update(self.base_params) r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) return r.json() if __name__ == '__main__': # 用户中心>>软件ID 生成一个替换 96001 # Chaojiying_Client三个参数 超级鹰用户名、密码、软件ID chaojiying = Chaojiying_Client('17800000000', '1234567890', '900000') # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要// im = open('code.png', 'rb').read() # im就是图片的所有字节(图片) # 1902 验证码类型 官方网站>>价格体系 print(chaojiying.PostPic(im, 1902))
如果是WIN系统,有时本地图片路径可能须要双斜杠//
有时python版本可能会提示 tab 空格错误,注意统一一下换行符就行
4、利用超级鹰破解超级鹰验证
注意到超级鹰网站作为验证码破解技术的提供方,自身的网站登录上同样也有着验证码,那么能否也用超级鹰进行破解登录?
测试代码如下:
改成自己的超级鹰账号、密码和软件ID即可
from selenium.webdriver import Chrome from chaojiying import Chaojiying_Client import time web = Chrome() web.get("http://www.chaojiying.com/user/login/") # 处理验证码 img = web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/div/img').screenshot_as_png chaojiying = Chaojiying_Client('17800000000', '1234567890', '900000') dic = chaojiying.PostPic(img, 1902) verify_code = dic['pic_str'] # 向页面中填入用户名, 密码, 验证码 web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[1]/input').send_keys("17800000000") web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[2]/input').send_keys("1234567890") web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[3]/input').send_keys(verify_code) time.sleep(5) # 点击登录 web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[4]/input').click()
5、cookie登录
登录后网站会利用cookie来识别用户的身份,那如果第一次登录就先获取cookie之后,后面登录直接利用注入保存的cookie,就省去了多次登录中超级鹰积分的消耗。当然有些网站的cookie的有生命周期,具体情况具体再去分析。
这里还是使用上面超级鹰破解超级鹰验证的代码进行改造。
保存cookie:
import json from selenium.webdriver import Chrome from chaojiying import Chaojiying_Client import time web = Chrome() web.get("http://www.chaojiying.com/user/login/") # 处理验证码 img = web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/div/img').screenshot_as_png chaojiying = Chaojiying_Client('17800000000', '1234567890', '90000') dic = chaojiying.PostPic(img, 1902) verify_code = dic['pic_str'] # 向页面中填入用户名, 密码, 验证码 web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[1]/input').send_keys("17861128200") web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[2]/input').send_keys("1234567890") web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[3]/input').send_keys(verify_code) time.sleep(5) # 点击登录 web.find_element_by_xpath('/html/body/div[3]/div/div[3]/div[1]/form/p[4]/input').click() # get_cookies() 函数获取当前网页的cookie值 with open('cookies.txt','w') as f: # 将cookies保存为json格式 f.write(json.dumps(web.get_cookies())) web.close()
注入cookie登录:
import time from selenium import webdriver import json # 填写webdriver的保存目录 driver = webdriver.Chrome() # 记得写完整的url 包括http和https driver.get('https://www.chaojiying.com/') # 首先清除由于浏览器打开已有的cookies driver.delete_all_cookies() with open('cookies.txt','r') as f: # 使用json读取cookies 注意读取的是文件 所以用load而不是loads cookies_list = json.load(f) for cookie in cookies_list: driver.add_cookie(cookie) # 进用户中心 driver.get('https://www.chaojiying.com/user/') time.sleep(3)
测试成功: