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)

测试成功:

 

posted @ 2021-05-11 17:21  王陸  阅读(468)  评论(0编辑  收藏  举报