0

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

    2023.12.04 | admin | 63次围观

    文章目录

    爬虫解决弹窗:

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

    常见alert式弹出框

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

    关于switch_to.alert( ) 参数 名称用法

    accept()

    点击Alert的【确认】按钮

    authenticate(username,password)

    给需要验证的Alert发送账号和密码,默认点击OK

    dismiss()

    点击Alert的【取消】按钮

    send_keys(keysToSend)

    在Alert的输入框输入信息

    text

    获取Alert上的文言信息

    switch_to.alert

    切换到Alert

    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式弹出框的处理

    这里给出第一种方式:

    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安装配置

    一般来说, 对于验证码,使用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的识别率没有那么高, 需要训练数集。

    版权声明

    本文仅代表作者观点。
    本文系作者授权发表,未经许可,不得转载。

    发表评论