python爬虫如何解决图片验证码


Posted in Python onFebruary 14, 2021

之前刚开始做爬虫的时候遇到过登录验证码问题,看过很多帖子都没有解决我的问题,发现大多数帖子都是治标不治本,于是想分享一下自己的解决方案。本次采用的网站是古诗文网,使用百度API,因为百度API免费!免费!免费!适合自己学习的时候使用。如果还没有使用过百度API识别验证码的朋友可以看一下我的这个帖子。
以下案例采用的时古诗文网:登录古诗文网,

1、selenium处理图片验证码

先定位到验证码图片,在获取验证码图片在页面中的位置,使用save_screenshot截取页面,再根据图片的位置去截取验证码,最后通过接口识别文字获取验证码,直接上代码:

element = driver.find_element_by_id('imgCode') # 定位验证码图片
# 获取验证码图片在网页中的位置
left = int(element.location['x'])  # 获取图片左上角坐标x
top = int(element.location['y'])  # 获取图片左上角y
right = int(element.location['x'] + element.size['width'])    # 获取图片右下角x
bottom = int(element.location['y'] + element.size['height'])  # 获取图片右下角y

# 通过Image处理图像
path = current_dir + str(random.random()) + '.png'  # 生成随机文件名
driver.save_screenshot(path)    # 截取当前窗口并保存图片
im = Image.open(path)        # 打开图片
im = im.crop((left, top, right, bottom))  # 截图验证码
im.save(path)    # 保存验证码图片

# 使用百度API识别验证码
def get_code():
  client = AipOcr(APP_ID, API_KEY, SECRET_KEY)  # 百度API文档中提供的方法识别文字

  # 由于我处理的验证码图片没有填多的线条,所以直接采用灰度是验证码数字更加清晰,具体的处理方式可根据验证码的实际情况而定
  im = Image.open(path)
  # 转换为灰度图像
  im = im.convert('L')
  im.save(path)

  # 读取图片,应为百度API中提供的方法参数只能是字节流
  with open(path, 'rb')as f:
    image = f.read()
  # 使用API中提供的方法识别验证码并返回验证码
  code = client.basicGeneral(image)

  print(code['words_result'][0]['words']) # {'words_result': [{'words': '4TBiD ', 'location': {'top': 1, 'left': 6, 'width': 43, 'height': 13}}], 'log_id': 1358288307112378368, 'words_result_num': 1}
  return code['words_result'][0]['words']

2、使用requests请求验证码

这里用到了会话机制,对于初学者来说可能不太了解,简单说一下会话机制的作用,会话就是用来保存你之前请求的cookie,让浏览器知道你之前就在这里,这样浏览器就不会认为你重新来到这里,从而刷新验证码,这样就可以带着我们获取的验证码去登录了。

conn = requests.Sessoin(  # 创建会话
resp = conn.get('https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx')
selector = Selector(text=resp.text)
img_url = 'https://so.gushiwen.cn/'+selector.xpath('.//img[@id="imgCode"]/@src').get() # 获取图片的路由
img = conn.get(img_url)  # 保持会话请求
filename = str(random.random()) + '.png'
with open(filename, 'wb')as f:
  f.write(img.content)
# 为了后面的调用接口识别不报图片格式错误,进行一次图片转换
im = Image.open(filename)
im.save(filename)
# 使用二进制方式读取图片
with open(filename, 'rb')as f:
image = f.read()
data = client.handwriting(image)  # diao'yong
# 使用API中提供的方法识别验证码并返回验证码
code = client.basicGeneral(image)
code = code['words_result'][0]['words']

selenium源码

# -* coding: utf-8 *-

import time
import random
from PIL import Image
from aip import AipOcr
from selenium.webdriver import Chrome

# 百度API参数
APP_ID = '23647800'
API_KEY = 'n95KOQgVuOMoAP72qZZo7uoN'
SECRET_KEY = '7yhyGglHUsY52DD8kf4w0Qjnxum07hMK'
client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # 调用API接口


def scrapy(username, password):
  """
  :param username:  用户名
  :param password:  密码
  """
  driver = Chrome()
  driver.get('https://so.gushiwen.cn/user/login.aspx')
  driver.find_element_by_id('email').send_keys(username) # 输入账号
  driver.find_element_by_id('pwd').send_keys(password)  # 输入密码

  element = driver.find_element_by_id('imgCode') # 定位验证码图片
  # 获取验证码图片在网页中的位置
  left = int(element.location['x']) # 获取图片左上角坐标x
  top = int(element.location['y']) # 获取图片左上角y
  right = int(element.location['x'] + element.size['width']) # 获取图片右下角x
  bottom = int(element.location['y'] + element.size['height']) # 获取图片右下角y

  # 通过Image处理图像
  filename = str(random.random()) + '.png' # 生成随机文件名
  driver.save_screenshot(filename) # 截取当前窗口并保存图片
  im = Image.open(filename) # 打开图片
  im = im.crop((left, top, right, bottom)) # 截图验证码
  im.save(filename) # 保存验证码图片
  # 由于我处理的验证码图片没有填多的线条,所以直接采用灰度是验证码数字更加清晰,具体的处理方式可根据验证码的实际情况而定
  im = Image.open(filename)
  # 转换为灰度图像
  im = im.convert('L')
  im.save(filename)
  # 读取图片,应为百度API中提供的方法参数只能是字节流
  with open(filename, 'rb')as f:
    image = f.read()
  # 使用API中提供的方法识别验证码并返回验证码
  data = client.basicGeneral(image)
  try:
    code = data['words_result'][0]['words']
  except:
    return data['error_msg']

  driver.find_element_by_id('code').send_keys(code)  # 输入验证码
  driver.find_element_by_id('denglu').click()   # 点击登录
  time.sleep(1000)  # 为了看清登录,等待1000秒


if __name__ == '__main__':
  print(scrapy(username, password)) # 传入你在古诗文网注册的账号密码

requests源码

# -* coding: utf-8 *-
import os
import random
import re
import requests
from PIL import Image
from aip import AipOcr
from scrapy import Selector

headers = {
  'referer': 'https://so.gushiwen.cn/user/login.aspx',
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36'
}

# 百度API参数
APP_ID = '23647800'
API_KEY = 'n95KOQgVuOMoAP72qZZo7uoN'
SECRET_KEY = '7yhyGglHUsY52DD8kf4w0Qjnxum07hMK'

def scrapy(username, password):
  """
  :param username:  用户名
  :param password:  密码
  """
  client = AipOcr(APP_ID, API_KEY, SECRET_KEY) # 调用API接口
  conn = requests.Session() # 创建会话
  resp = conn.get('https://so.gushiwen.cn/user/login.aspx', headers=headers) # 获取登录页面
  selector = Selector(text=resp.text)
  __VIEWSTATE = selector.xpath('.//input[@id="__VIEWSTATE"]/@value').get()
  __VIEWSTATEGENERATOR = selector.xpath('.//input[@id="__VIEWSTATEGENERATOR"]/@value').get()
  img_url = 'https://so.gushiwen.cn/' + selector.xpath('.//img[@id="imgCode"]/@src').get() # 获取图片的路由
  img = conn.get(img_url, headers=headers) # 获取图片路由
  # 保存图片
  filename = str(random.random()) + '.png' # 随机生成文件名, 图片格式不能为jpg,API不支持jpg格式的识别
  with open(filename, 'wb')as f:
    f.write(img.content)
   # 由于我处理的验证码图片没有填多的线条,所以直接采用灰度是验证码数字更加清晰,具体的处理方式可根据验证码的实际情况而定
  im = Image.open(filename)
  # 转换为灰度图像
  im = im.convert('L')
  im.save(filename)
  # 使用二进制方式读取图片
  with open(filename, 'rb')as f:
    image = f.read()
  # # 标准识别, 每天免费50000次
  # data = client.basicGeneral(image)
  # 精确识别,每天免费500次
  data = client.handwriting(image)
  # 捕获一下接口识别当中的错误,可参照文档查看报错原因
  try:
    code = data['words_result'][0]['words']
  except:
    return data['error_msg']
  form_data = {
    '__VIEWSTATE': __VIEWSTATE,
    '__VIEWSTATEGENERATOR': __VIEWSTATEGENERATOR,
    'from': '',
    'email': username,
    'pwd': password,
    'code':cod,
    'denglu': '登录'
  }
  # 登录
  html = conn.post('https://so.gushiwen.cn/user/login.aspx', headers=headers, data=form_data).text
  # 获取登录标志位
  login_flag = re.findall("alert\('(.*?)'\);",html)[0] if re.findall("alert\('(.*?)'\);",html) else ''
  if not login_flag:
    return '登录成功!'
  elif '验证码有误!' in login_flag:
    return "验证码错误"


if __name__ == '__main__':
  print(scrapy(username, password))

以上就是python爬虫如何解决图片验证码的详细内容,更多关于python 解决图片验证码的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
py2exe 编译ico图标的代码
Mar 08 Python
python实现的一个p2p文件传输实例
Jun 04 Python
简单介绍利用TK在Python下进行GUI编程的教程
Apr 13 Python
K-means聚类算法介绍与利用python实现的代码示例
Nov 13 Python
Python实现修改文件内容的方法分析
Mar 25 Python
PyQt5每天必学之QSplitter实现窗口分隔
Apr 19 Python
python如何创建TCP服务端和客户端
Aug 26 Python
python批量下载抖音视频
Jun 17 Python
对python 中re.sub,replace(),strip()的区别详解
Jul 22 Python
django日志默认打印request请求信息的方法示例
May 17 Python
Idea安装python显示无SDK问题解决方案
Aug 12 Python
Python编程中内置的NotImplemented类型的用法
Mar 23 Python
Python实现粒子群算法的示例
Feb 14 #Python
Python中对象的比较操作==和is区别详析
Feb 12 #Python
python绘图模块之利用turtle画图
Feb 12 #Python
Python列表的深复制和浅复制示例详解
Feb 12 #Python
Python就将所有的英文单词首字母变成大写
Feb 12 #Python
详解Java中一维、二维数组在内存中的结构
Feb 11 #Python
SpringBoot首页设置解析(推荐)
Feb 11 #Python
You might like
新版PHP极大的增强功能和性能
2006/10/09 PHP
php下实现折线图效果的代码
2007/04/28 PHP
php mssql 分页SQL语句优化 持续影响
2009/04/26 PHP
PHP下escape解码函数的实现方法
2010/08/08 PHP
php压缩HTML函数轻松实现压缩html/js/Css及注意事项
2013/01/27 PHP
PHP生成随机密码方法汇总
2015/08/27 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
yii2.0实现创建简单widgets示例
2016/07/18 PHP
PHP仿微信发红包领红包效果
2016/10/30 PHP
PHP正则匹配到2个字符串之间的内容方法
2018/12/24 PHP
心扬JS分页函数代码
2010/09/10 Javascript
js面向对象 多种创建对象方法小结
2012/05/21 Javascript
基于jquery的跟随屏幕滚动代码
2012/07/24 Javascript
javascript中验证大写字母、数字和中文
2014/01/15 Javascript
jQuery实现视频作为全屏幕背景
2014/12/18 Javascript
JavaScript中反正弦函数Math.asin()的使用简介
2015/06/14 Javascript
Underscore.js 1.3.3 中文注释翻译说明
2015/06/25 Javascript
JavaScript数组push方法使用注意事项
2017/10/30 Javascript
JS实现table表格内针对某列内容进行即时搜索筛选功能
2018/05/11 Javascript
使用VUE实现在table中文字信息超过5个隐藏鼠标移到时弹窗显示全部
2019/09/16 Javascript
ES6 Iterator遍历器原理,应用场景及相关常用知识拓展详解
2020/02/15 Javascript
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
使用python编写简单的小程序编译成exe跑在win10上
2018/01/15 Python
Python中XlsxWriter模块简介与用法分析
2018/04/24 Python
利用python打开摄像头及颜色检测方法
2018/08/03 Python
利用Django-environ如何区分不同环境
2018/08/26 Python
python-numpy-指数分布实例详解
2019/12/07 Python
Python GUI之tkinter窗口视窗教程大集合(推荐)
2020/10/20 Python
小橄榄树:Le Petit Olivier
2018/04/23 全球购物
美国克罗格超市在线购物:Kroger
2019/06/21 全球购物
DeinDesign德国:设计自己的手机壳
2019/12/14 全球购物
企业授权委托书范本
2014/04/02 职场文书
2014年大学班长工作总结
2014/11/14 职场文书
2015年检验员工作总结范文
2015/04/30 职场文书
详解CSS不受控制的position fixed
2021/05/25 HTML / CSS
docker-compose部署Yapi的方法
2022/04/08 Servers