Python爬虫编程6——selenium

目录

爬虫和反爬虫的斗争

爬虫建议

ajax基本介绍

动态了解HTML技术

获取ajax数据的方式

一.Selenium+chromedriver

Selenium介绍

Phantomjs快速入门

Phantomjs案例

selenium快速入门

定位元素

操作表单数据

鼠标行为链

Selenium页面等待

Cookie操作

页面等待

打开多窗口和切换页面

特征识别和设置无头窗口

selenium常用的js操作

二.图形验证码识别

Tesseract安装以及操作

云打码平台的使用


爬虫和反爬虫的斗争

爬虫建议

(1)尽量减少请求次数,保存或取的HTML,供查错和重复使用;

(2)关注网站的所有类型的页面,H5页面,APP等等;

(3)设置多伪装,代理IP,随即请求头等;

(4)利用多线程分布式,再不被发现的情况下我们尽可能提高速度。

ajax基本介绍

动态了解HTML技术

(1)JS:是网络上最常用的脚本语言,它可以收集用户的跟踪数据,不需要重载页面直接提交表单,在页面嵌入多媒体文件,甚至运行网页;

(2)jQuery:jQuery是一个快速,简介的JavaScript框架,封装了JavaScript常用的功能代码;

(3)ajax:ajax可以使用网页实现异步更新,可以在不重新加载整个页面的情况下,对页面的某部分进行更新。

获取ajax数据的方式

(1)直接分析ajax调用的接口。然后通过代码请求这个接口;

(2)使用Selenium+chromedriver模拟浏览器行为获取数据;

一.Selenium+chromedriver

Selenium介绍

1.selenium是一个web的自动化测试工具,最初是为网站自动化测试而开发的,selenium可以直接运行在浏览器上,它支持所有主流的浏览器,可以接受指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏。

2.chromedriver是一个驱动Chorme浏览器的驱动程序,使用它才可以驱动浏览器。当然针对不同的浏览器有不同的driver。以下列出了不同浏览器及其对应的driver:

(1)Chrome:https://sites.google.com/a/chromium.org/chromedriver/downloads

(2)Firefox:Releases · mozilla/geckodriver · GitHub

(3)Edge:Microsoft Edge Driver - Microsoft Edge Developer

(4)Safari:WebDriver Support in Safari 10 | WebKit

Phantomjs快速入门

无头浏览器:一个完整的浏览器内核,包含js解析引擎,渲染引擎,请求处理等,但是不包含显示和用户的页面的浏览器。

Phantomjs案例

# 1.加载网页
from selenium import webdriver
driver = webdriver.PhantomJS("安装目录")
driver.get("https://www.baidu.com")
driver.save_screenshot("baidu.png")

# 2.定位和操作
driver.find_element_by_id("kw").send_keys("长城")
driver.find_element_by_id("su").click()

# 3.查看请求信息
driver.page_source
driver.get_cookies()
driver.current_url

# 4.退出
driver.quit() 

注意:在新版的selenium中没有Phantomjs,所以这里不做更多的解释。

selenium快速入门

from selenium import webdriver

# 实例化浏览器
driver = webdriver.Chrome()

# 发送请求
driver.get('https://www.baidu.com')

# 退出浏览器
driver.quit()

定位元素

(1)find_element_by_id:根据id查找某个元素:

submitTag = driver.find_element_by_id('su')
submitTag1 = driver.find_element(By.ID,'su')

(2)find_element_by_class_name:根据类名查找某个元素:

submitTag = driver.find_element_by_class_name('su')
submitTag1 = driver.find_element(By.CLASS_NAME,'su')

(3)find_element_by_name:根据name属性值查找某个元素:

submitTag = driver.find_element_by_name('email')
submitTag1 = driver.find_element(By.NAME,'email')

(4)find_element_by_tag_name:根据标签名查找某个元素:

submitTag = driver.find_element_by_tag_name('div')
submitTag1 = driver.find_element(By.TAG_NAME,'div')

(5)find_element_by_xpath:根据xpath语法查找某个元素:

submitTag = driver.find_element_by_xpath('//div')
submitTag1 = driver.find_element(By.XPATH,'//div')

注意使用上述的小by方法定位元素时,会有一个报警,这是因为这个方法即将过时,而大By方法,则不会出现报警,但是要导包:

from selenium.webdriver.common.by import By

且注意,find_element是获取第一个满足条件的元素。find_elements是获取所有满足条件的元素。

操作表单数据

操作输入框:分为两步。

第一步:找到这个元素。

第二步:使用send_keys(values),将数据填充进去。

(1)使用clear方法可以清除输入框中的内容

inputTag.clear()

(2)操作按钮

操作按钮有很多种方式,比如单击,右击,双击等。这里讲两个最常用的。就是点击,直接调用click函数就可以了。

inputTag = driver.find_element_by_id('su')
# 点击函数
inputTag.click()

(3)选择select

select元素不能直接点击。因为点击后还需要选中元素。这时候selenium就专门为select标签提供了一个类from selenium.webdriver.support.ui import Select。将获取到的元素当成参数传到这个类中,创建这个对象。以后就可以使用这个对象进行选择了。(注意有时要切换到一个新的标签iframe中)

测试网站:https://www.17sucai.com/pins/demo-show?id=5926

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import time


driver = webdriver.Chrome()
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')

# 找到iframe
iframe_tag = driver.find_element_by_id('iframe')
# 切换到iframe
# 旧方法
# driver.switch_to_frame(iframe_tag)
# 新方法
driver.switch_to.frame(iframe_tag)

# 定位到select标签
# Message: no such element: Unable to locate element: {"method":"css selector","selector":".nojs"}
select_tag = driver.find_element_by_class_name('nojs')

new_select_tag = Select(select_tag)

# 根据值来选择
# new_select_tag.select_by_value('AU')

# 根据索引选择
new_select_tag.select_by_index(1)
"""
两种选择方式
一种是根据值来选择
另一种是通过索引选择
"""

鼠标行为链

有时候在页面中的操作可能要有很多步,那么这时候可以使用鼠标行为链类ActionChains来完成。比如现在要将鼠标移动到某个元素上并执行点击事件。

import time
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get('https://www.baidu.com/?tn=49055317_3_hao_pg')

# 定位输入框
input_baidu = driver.find_element(By.XPATH, '//*[@id="kw"]')

# 定位百度按钮
btn_baidu = driver.find_element(By.XPATH, '//*[@id="su"]')

actions = ActionChains(driver)

# 往输入框种输入内容
actions.send_keys_to_element(input_baidu, 'python')
time.sleep(2)
# 移动鼠标位置
actions.move_to_element(btn_baidu)
actions.click()


# 提交行为链,必不可少
actions.perform()

还有更多的鼠标相关的操作

  • click_and_hold(element):点击但不松开鼠标。
  • context_click(element):右键点击。

行为链小练习:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import time

# 1 找到滑块
# 2 拖动小滑块
# 3 到大滑块松开鼠标

driver = webdriver.Chrome()

driver.get('https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')

ifarme = driver.find_element(By.ID,'iframeResult')

driver.switch_to.frame(ifarme)

# 小滑块
div1 = driver.find_element(By.ID,'draggable')

# 大滑块
div2 = driver.find_element(By.ID,'droppable')

# 创建行为链
ac = ActionChains(driver)

# 点击并且不松开
ac.click_and_hold(div1)

# 拖动到大的div
# ac.move_to_element(div2)

# ac.move_by_offset(300,0)
for i in range(6):
    time.sleep(0.1)
    ac.move_by_offset(50, 0)

# 松开鼠标
ac.release()

# 提交行为链
ac.perform()

测试网站:https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable

Selenium页面等待

Cookie操作

(1)获取所有的cookie

cookies = driver.get_cookies()

(2)根据cookie的name获取cookie

value = driver.get_cookie(name)

(3)删除某个cookie

driver.delete_cookie('key')

案例:利用selenium得到的cookie登录qq空间:

from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import requests

# 通过selenium获取cookie
"""
1 通过selenium获取cookie值
2 进一步解析拼接cookie值
3 把最终拼接好的cookie值放测试代码中做测试
"""
# 1 通过selenium获取cookie值
# 加载驱动
driver = webdriver.Chrome()
# 打开一个网站
driver.get('https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&pt_qr_app=手机QQ空间&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html&pt_no_auth=0')

time.sleep(2)

# 找到头像
# link = driver.find_element_by_id('img_out_2857223830')
link = driver.find_element_by_class_name('face')
# 点击
link.click()
# 等待页面加载一会儿
time.sleep(2)
raw_cookie = driver.get_cookies()
# print(raw_cookie)
# 列表推导式
cookie = [item['name'] + '=' + item['value'] for item in raw_cookie]
# cookie_plus = "; ".join(cookie)
cookie_plus = "; ".join(i for i in cookie)
print(cookie_plus)

# cookie = []
# for i in raw_cookie:
#     n = i['name']
#     v = i['value']
#     # n=v
#     lst = n + '=' + v
#     cookie.append(lst)
# # print(cookie)
# cookie_plus = "; ".join(cookie)
# print(cookie_plus)




# 测试代码 如果把通过selenium获取到的cookie放进请求头中 能够模拟登录成功 就证明我们通过selenium获取到的cookie是没有问题的
# url = 'https://user.qzone.qq.com/2857223830/infocenter'
#
# header = {
#     'cookie': cookie_plus,
#     'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
# }
#
# html = requests.get(url, headers=header)
# with open('qzone.html', 'w', encoding='utf-8') as f:
#     f.write(html.content.decode('utf-8'))

页面等待

现在的网页越来越多采用了 Ajax 技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以 Selenium 提供了两种等待方式:一种是隐式等待、一种是显式等待。

(1)隐式等待:调用driver.implicitly_wait。那么在获取不可用的元素之前,会先等待10秒中的时间。

driver.implicitly_wait(10)

(2)显式等待:显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用selenium.webdriver.support.excepted_conditions期望的条件和selenium.webdriver.support.ui.WebDriverWait来配合完成。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")

element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
 )

一些其他的等待条件

  • presence_of_element_located:某个元素已经加载完毕了。
  • presence_of_all_elements_located:网页中所有满足条件的元素都加载完毕了。

打开多窗口和切换页面

有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

driver = webdriver.Chrome()
driver.get('https://www.baidu.com/?tn=49055317_3_hao_pg')
driver.implicitly_wait(3)
# driver.get('https://www.douban.com/?tn=49055317_3_hao_pg')
# 用js打开多个窗口
driver.execute_script('window.open("https://www.douban.com/?tn=49055317_3_hao_pg")')
time.sleep(2)
# 打开一个新窗口,如果想对新窗口进行操作,就要先切换selenium的视角
driver.switch_to.window(driver.window_handles[1])
# 打印当前视角的url
print(driver.current_url)
driver.close()     # 使用close关闭之后,最好切换一下窗口,有残留。最好不要使用

特征识别和设置无头窗口

(1)设置无头窗口(运行时不会在打开浏览器)

from selenium import webdriver

# 创建一个设置对象
option = webdriver.ChromeOptions()
option.add_argument('--headless')

driver = webdriver.Chrome(options=option)

driver.get('https://www.baidu.com')

driver.save_screenshot('baidu.png')

(2)特征识别

有时候我们在使用selenium爬取某网站时,会被网站识别成一个自动化测试的程序,从而会导致我们得不到想要的数据,我们这时需要去除一下特征识别:

from selenium import webdriver
import time
from selenium.webdriver.common.by import By


# 去除识别 去除提示框
# option = webdriver.ChromeOptions()
# option.add_experimental_option('excludeSwitches', ['enable-automation'])
# option.add_experimental_option("detach", True)
#

# driver = webdriver.Chrome(options=option)
#
# driver.get('https://www.baidu.com')

# selenium打开的浏览器navigator.webdriver属性为true

# 把navigator.webdriver属性改为false
# script = 'Object.defineProperty(navigator, "webdriver", {get: () => false,});'
# driver.execute_script(script)

option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
option.add_experimental_option("detach", True)

driver = webdriver.Chrome(options=option)

driver.get('http://www.porters.vip/features/webdriver.html')

driver.execute_script('Object.defineProperty(navigator, "webdriver", {get: () => false,});')

driver.find_element(By.XPATH,'//button[@class="btn btn-primary btn-lg"]').click()

selenium常用的js操作

(94条消息) selenium中常用的js操作_weixin_46583017的博客-CSDN博客icon-default.png?t=M1H3https://blog.csdn.net/weixin_46583017/article/details/113738948?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164515283116780269839445%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164515283116780269839445&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-1-113738948.first_rank_v2_pc_rank_v29&utm_term=selenium%E7%9A%84js%E6%93%8D%E4%BD%9C&spm=1018.2226.3001.4187

二.图形验证码识别

Tesseract安装以及操作

阻碍我们爬虫的。有时候正是在登录或者请求一些数据时候的图形验证码。因此这里我们讲解一种能将图片翻译成文字的技术。将图片翻译成文字一般被称为光学文字识别(Optical Character Recognition),简写为OCR。实现OCR的库不是很多,特别是开源的。因为这块存在一定的技术壁垒(需要大量的数据、算法、机器学习、深度学习知识等),并且如果做好了具有很高的商业价值。因此开源的比较少。这里介绍一个比较优秀的图像识别开源库:Tesseract。

  • Tesseract是一个将图像翻译成文字的OCR(光学文字识别,Optical Character Recognition),目前由谷歌赞助。Tesseract是目前公认最优秀、最准确的开源OCR库。Tesseract具有很高的识别度,也具有很高的灵活性,他可以通过训练识别任何字体
  • Windows系统安装 在以下链接下载可执行文件,https://github.com/tesseract-ocr/

在python中安装:pip install pytesseract

设置环境变量:

安装完成后,如果想要在命令行中使用Tesseract,那么应该设置环境变量。Mac和Linux在安装的时候就默认已经设置好了。在Windows下把tesseract.exe所在的路径添加到PATH环境变量中。

识别中文图像,需要下载语言安装包:

URL地址:https://github.com/tesseract-ocr/tessdat

# 命令行使用
#   tesseract --help 查看帮助
#   tesseract --list-langs 查看可识别的语言
#   tesseract 图片名称 返回的文件名 识别前需要先cd到图片的目录
#   tesseract 图片名称 返回的文件名 -l 需要识别的语言

在python中使用:

# 在python中使用tesseract识别图片 需要下载两个库
#   1 pip install pytesseract 用来操作 tesseract
#   2 pip install pillow 用于处理图片

# 导包
#   1 import pytesseract
#   2 from PIL import Image

import pytesseract
from PIL import Image
import urllib.request

# 打开图片
aaa = Image.open('aaa.png')

# 把图片识别成文字
result_aaa = pytesseract.image_to_string(aaa)

print(result_aaa)

bbb = Image.open('bbb.png')

# image_to_string(bbb,lang='chi_sim') 设置识别的语言 chi_sim(简体中文)
result_bbb = pytesseract.image_to_string(bbb,lang='chi_sim')

print(result_bbb)


# 验证码网址
url = 'https://passport.lagou.com/vcode/create?from=register&refresh=1513081451891'

# 保存图片 urllib.request.urlretrieve(网址,'图片名称')
# urllib.request.urlretrieve(url,'ccc.png')

ccc = Image.open('ccc.png')

result_ccc = pytesseract.image_to_string(ccc)

print(result_ccc)

云打码平台的使用

由于tesseract对于一些高级的验证并无法做到准确,所以我们可以使用在线打码平台,这里推荐一个打码平台:超级鹰。网址:超级鹰验证码识别-专业的验证码云端识别服务,让验证码识别更快速、更准确、更强大 (chaojiying.com)icon-default.png?t=M1H3https://www.chaojiying.com/

在超级鹰里面可以选择下载python的使用文档说明:

#!/usr/bin/env python
# coding:utf-8

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__':
	chaojiying = Chaojiying_Client('用户名', '密码', '手动生成的软件id')	#用户中心>>软件ID 生成一个替换 96001
	# 打开图片
	im = open('ccc.png', 'rb').read()
    # print(chaojiying.PostPic(图片, 识别验证码的类型))
	print(chaojiying.PostPic(im, 1902))											#1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()

这里我们在使用的时候,直接调用即可使用方式如下:

注意我们不需要额外在下载其他的库,直接导入chaojiying这个包即可,有的时候导入包的时候会报错,不必理会,没有影响,只要我们将用户名,密码,id输入正确即可。

# 不影响使用
from chaojiying import Chaojiying_Client

# Chaojiying_Client('用户名', '用户密码', '手动生成的软件id') 创建对象
chaojiying = Chaojiying_Client('用户名', '密码', '手动生成的软件id')

# 打开图片
im = open('ddd.png', 'rb').read()
# print(chaojiying.PostPic(图片, 识别验证码的类型))

# chaojiying.PostPic(图片, 类型)
print(chaojiying.PostPic(im, 9004))

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值