小言_互联网的博客

python爬虫中关于弹窗和验证码解决思路!

382人阅读  评论(0)

本篇博客分享关于我在爬虫中如何解决弹窗,以及解决验证码的一种思路,仅作为参考,不同网站和不同验证码可能不能如法炮制,如果不能完全实现,请原谅! 时间: 2020年8月

如果看完有收获, 喜欢的话,记得关注,收藏一波哦!

爬虫解决弹窗:

弹窗本来是用来警告或者提示信息, 也可以起到反爬的作用, 而对于一个爬虫工作人员来说, 我们还是要解决这个弹窗问题。 弹窗的实质也就是网页的js脚本, 有些弹窗他是一次性的, 作为检测你是否是第一次登入, 这样的弹窗你爬虫之前先进去一次就可以搞定, 其他的弹窗的话,还是得看一下网页源码, 对症下药。 而一般弹窗会存放到第一个节点 script 里面 ,也有特殊情况。读懂网页源码,才是解决的最好办法。


常见alert式弹出框

  • alert(message)显示警告或其他信息,用于通知用户,下方只有一个【确认】按钮。
  • confirm(message)询问是否继续某种操作等功能,下方有【确认】和【取消】两种按钮
  • prompt(text, defaultText),需要输入一些信息,比如用户密码等,下方会有【确认】和【取消】按扭

新版本 selenium 中语法规则已经改掉, 现在为 driver.switch_to.alert.accept()

  • 这类弹窗可以使用 selenium工具的 switch_to.alert() 方式 去处理 具体如下:

关于switch_to.alert( ) 参数

名称 用法
accept() 点击Alert的【确认】按钮
authenticate(username,password) 给需要验证的Alert发送账号和密码,默认点击OK
dismiss() 点击Alert的【取消】按钮
send_keys(keysToSend) 在Alert的输入框输入信息
text 获取Alert上的文言信息
switch_to.alert 切换到Alert
  • 这里用js代码生成一个弹窗, 使用该函数试一试流程, 是如何解决的!
url = 'http://www.baidu.com'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)
# driver.execute_script("window.alert('这是一个测试Alert弹窗');")
driver.execute_script("window.confirm('这也是一个测试窗口')")
time.sleep(2)
a = driver.switch_to.alert.text  # 捕获弹窗 获得文本信息
print(a)
driver.switch_to.alert.dismiss()  # 捕获弹窗,点击取消
time.sleep(2)
driver.quit()

如果不是传统的alert弹窗类型

大致意思就是, 你用前面的方式行不通了, 你再来试试用这些方法。

非传统alert式弹出框的处理

  • 弹出框位于div层,跟平常定位方法一样
  • 弹出框是嵌套的iframe层,需要切换iframe
  • 弹出框位于嵌套的handle,需要切换窗口

这里给出第一种方式:

from selenium import webdriver
import time

url = 'http://www.baidu.com'
driver = webdriver.Chrome()
driver.maximize_window()
driver.get(url)
time.sleep(1)
driver.find_driver.find_element_by_xpath("弹窗点击按钮").click()
# 另外二种, 使用 browser.switch_to.frame('main') 先切换
#  或者  browser.execute_script('window.open()')  # 新建选项卡 功能
#      browser.switch_to.window(browser.window_handles[1])

最后一个办法

老铁们, 实在解决不了的, 直接手动把弹窗关掉吧, 但是如果是我的话, 我得花点时间研究一下, 毕竟能解决一个新的问题,对我收获很大! 哈哈, 这里皮一下!

爬虫解决验证码:

验证码也是反爬的一个鼻祖吧, 最开始就是用验证码的, 然后现在五花八门, 滑动的, 滑动卡位的, 猜数的, 猜文字的, 越来越欺负人了, 只不过为了模拟登入而已, 真考验人, 这里我用的方式是tesseract, 实话说, 这个成功率不是很高, 配置也很麻烦, 后期需要训练数集, 才能达到识别率高的效果, 不过还是分享一下。

关于tesseract安装配置

  • 在python中, 需要安装 pytesseract 库
  • 基础安装我就不讲了, 下好这个然后安装就行了。

  • 下载中文识别包, 放到database文件夹里面。

  • 环境变量 这个可以去设置, 但是我没有设置, 我是直接在使用的时候指定了工具和工具包的位置!

  • pytesseract中更改 tesseract_cmd 的路径:

一般来说, 对于验证码,使用tesseract我们至少来说要做三步。

1: 爬验证码,保存, 截取验证码


比如,我们要登入这个网站,要获取这个验证码,思路如下:

from PIL import Image
import pytesseract
import tesserocr
from selenium import webdriver
import time

url = 'https://authserver.nju.edu.cn/authserver/login'

driver = webdriver.Chrome()
driver.get(url)
driver.maximize_window()  # 最大化窗口
time.sleep(2)

# 切换验证码登入 因为进去是显示账号登入 
driver.find_element_by_xpath('//*[@id="dyLogin"]').click()
time.sleep(1)
# 图片节点 拿下来
img = driver.find_element_by_xpath('//*[@id="dynamicCodeChangeCaptcha"]')

location = img.location
size = img.size
# 不同图片 参数不一样的,这里我实验了几次,得到如下参数
left = location['x'] + 250
top = location['y'] + 90
right = left + size['width'] + 100
bottom = top + size['height'] + 20
driver.save_screenshot('valicode.png')
page_snap_obj = Image.open('valicode.png')
image_obj = page_snap_obj.crop((left, top, right, bottom))
image_obj.show()
image_obj.save("valicode.png")

driver.quit()

2: 图片灰度转换, 二值化, 去噪点

经过上面一步, 我们拿到了一张只包含验证码的图片, 但是需要进行进一步处理。

image_obj = Image.open('valicode.png')
    img = image_obj.convert("L")  # 转灰度图
    pixdata = img.load()
    w, h = img.size
    threshold = 120  # 这个120 也是自己实践得到, 不是每次都是120
    # 遍历所有像素,大于阈值的为黑色
    for y in range(h):
        for x in range(w):
            if pixdata[x, y] < threshold:
                pixdata[x, y] = 0
            else:
                pixdata[x, y] = 255

    data = img.getdata()
    w, h = img.size
    black_point = 0
    for x in range(1, w - 1):
        for y in range(1, h - 1):
            mid_pixel = data[w * y + x]
            if mid_pixel < 50:
                top_pixel = data[w * (y - 1) + x]
                left_pixel = data[w * y + (x - 1)]
                down_pixel = data[w * (y + 1) + x]
                right_pixel = data[w * y + (x + 1)]
                if top_pixel < 10:
                    black_point += 1
                if left_pixel < 10:
                    black_point += 1
                if down_pixel < 10:
                    black_point += 1
                if right_pixel < 10:
                    black_point += 1
                if black_point < 1:
                    img.putpixel((x, y), 255)
                black_point = 0
    img.show()
    img.convert('L')
    img.save('valicode.png')

然后就得到了一张这样的图片

3: 使用pytesseract进行图片的识别

    img = Image.open('valicode.png')
    img.show()
    # 这个是tesseract路径
    pytesseract.pytesseract.tesseract_cmd = 'D:/Tesseract-OCR/tesseract.exe'
    # 这个是识别包路径
    dir_config = '--tessdata-dir "D:/Tesseract-OCR/tessdata"'
    # 下面如果识别的中文, 可以指定 lang = "chi_sim"
    result = pytesseract.image_to_string(img, config=dir_config)
    print(result)

嘿嘿, 很抱歉, 我没有识别出来, 哈哈哈哈哈哈。操作了一整晚,为什么没成功识别,我也很纳闷, 我觉得还是图片没有处理好, 可能还需要去一下噪点什么的, 总之,思路大概是这样的, 如果有懂行的,知道怎么解决的,欢迎评论区告诉我你的方法, 多谢!

其他方法:

花钱找打码平台 或者 手动输入验证码 ! tesseract的识别率没有那么高, 需要训练数集。


转载:https://blog.csdn.net/qq_45906219/article/details/107824777
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场