大大文学网,热电厂爆炸致21死,qq旋风官网
目录
@
今天要搞定的验证码属于现在使用非常多的验证码的一种类型---极验证滑动验证码,关于这个验证码的详细说明查阅他的官网,https://www.geetest.com/ 把验证码做到这个地步,必须点赞了。
官方demo最新的效果如下,按照验证码的更新频率,基本博客看完,验证码也更新了,不过套路依旧是相同的,反爬只能增加爬虫编写的成本,并不能完全杜绝爬虫。
这类验证码,常规解决办法,模拟人为操作,图像比对,查找缺口,移动覆盖缺口。
今天看新闻,随意找了一下,虎嗅使用的是直接拖拽,没有用最新的点击+拖拽方式,可以直接看一下如何操作。
这种验证码除了打码平台以外,直接selenium搞起
当你在谷歌浏览器使用f12进行查找元素的时候,随意的去缺口图片上面点击一下,在控制台dom结构中出现如下代码,有前端经验的童鞋知道,这个使用的是背景局部显示技术,是可以通过这个拼接成一个。
注意两个地方:
312x116
使用selenium执行的操作,模拟人的点击行为即可
最初,我们导入一些selenium的基本模块与方法
import time import re from selenium import webdriver from selenium.common.exceptions import timeoutexception from selenium.webdriver.common.by import by from selenium.webdriver.support.wait import webdriverwait from selenium.webdriver.support import expected_conditions as ec from selenium.webdriver.common.action_chains import actionchains
基本模块的作用如下
webdriver 核心驱动
selenium.common.exceptions 异常类 timeoutexception 超时异常
selenium.webdriver.common.by 按照什么方式进行元素的查找 例如 by.id,by.classname,by.xpath
selenium.webdriver.support.wait 等待页面加载某些元素
from selenium.webdriver.support import expected_conditions 场景判断用的,一般和上面的等待加载元素一起使用
selenium.webdriver.common.action_chains 鼠标执行的动作链
主方法测试入口
if __name__ == '__main__': h = geek_huxiu() h.run()
构造方法,实现对部分参数的初始化操作
def __init__(self): self.driver = webdriver.chrome() self.driver.set_window_size(1366,768)
webdriver.chrome() 启动谷歌浏览器,这个地方需要你提前配置好chromedriver.exe
set_window_size(1366,768) 初始化浏览器大小
def run(self): self.driver.get("https://www.huxiu.com/") # 打开浏览器 webdriverwait(self.driver,10).until(ec.element_to_be_clickable((by.xpath,'//*[@class="js-register"]'))) reg_element = self.driver.find_element_by_xpath('//*[@class="js-register"]') reg_element.click() webdriverwait(self.driver,10).until(ec.element_to_be_clickable((by.xpath,'//div[@class="gt_slider_knob gt_show"]'))) # 模拟拖动 self.analog_drag()
webdriverwait 方法
说明
driver: 传入webdriver实例,即我们上例中的driver timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间) poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒 ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常, 则不中断代码,继续等待; 如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有nosuchelementexception。
基本使用方法
webdriverwait(driver, 超时时长, 调用频率, 忽略异常).until(可执行方法, 超时时返回的信息)
def analog_drag(self): # 鼠标移动到拖动按钮,显示出拖动图片 element = self.driver.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]') actionchains(self.driver).move_to_element(element).perform() time.sleep(3) # 刷新一下极验证图片 element = self.driver.find_element_by_xpath('//a[@class="gt_refresh_button"]') element.click() time.sleep(1) # 获取图片地址和位置坐标列表 cut_image_url,cut_location = self.get_image_url('//div[@class="gt_cut_bg_slice"]') print(cut_image_url) print(cut_location)
行为链
actionchains(self.driver).move_to_element(element).perform()
模拟人移动鼠标到指定dom元素
def get_image_url(self,xpath): link = re.compile('background-image: url\("(.*?)"\); background-position: (.*?)px (.*?)px;') elements = self.driver.find_elements_by_xpath(xpath) image_url = none location = list() for element in elements: style = element.get_attribute('style') groups = link.search(style) url = groups[1] x_pos = groups[2] y_pos = groups[3] location.append((int(x_pos), int(y_pos))) if not image_url: image_url = url return image_url, location
使用正则表达式进行匹配的时候,需要将所有的div匹配出来 ,采用find_elements_by_xpath
方法,尤其注意elements
webelement 具备一些常用的方法和属性
看下图,注意一些基本元素,拼接的图片由n个小矩形构成,分为上下两个部分,小矩形的宽度和高度为10x58
核心由上下两部分构成,每部分都是26个小矩形
因为,整体宽度为2610 = 260px ,整体高度为582=116px
但是,还记得博客开始的时候,你记录的那个宽度和高度么? 312x116
高度一致,但是宽度出现偏差
312-260 = 52px
52个像素去除以26个矩形,发现每个矩形差2px,这两个像素也就是下面我们拼接图片的重点了
def splicing_image(self,image_url,location): res = requests.get(image_url) file = bytesio(res.content) img = image.open(file) image_upper = [] image_down = [] for pos in location: if pos[1] == 0: # y值为0的坐标 属于图片上半部分,高度58 image_upper.append(img.crop((abs(pos[0]), 0, abs(pos[0]) + 10, 58))) else: # y值为58的坐标 属于图片上半部分,高度58 image_down.append(img.crop((abs(pos[0]), 58, abs(pos[0]) + 10, img.height))) # 画布的x轴偏移量 x_offset = 0 # 创建一张画布 new_img = image.new("rgb", (260, img.height)) for img in image_upper: new_img.paste(img, (x_offset, 58)) x_offset += img.width x_offset = 0 for img in image_down: new_img.paste(img, (x_offset, 0)) x_offset += img.width return new_img
说明
最终实现效果
# 将图片存储到本地 cut_image.save("cut.jpg") full_image.save("full.jpg")
好了,今天博客就先把图片处理到位,明天着手拼接部分。
欢迎关注「非本科程序员」 回复 【0412】获取本篇博客源码
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
新手学习Python2和Python3中print不同的用法
Python基于os.environ从windows获取环境变量
网友评论