爬虫软件识别数字二维码

背景:根据学生的信息(准考证号、学号、身份证后六位)信息,去官方网站查询考试成绩。一个年级300多个人,挨个查一遍,要多半天才能完成。所以希望能用python写一个爬虫程序,自动读取excell文件的信息,然后填写到网站上,自动识别录入验证码后,点击查询按钮,在弹出的新页面中,爬取各个学科的分数(例如:语文、数学)和总分,写到excell中另存为一个excell表。

这里面读取excell中的信息,使用chrome浏览器打开网页,自动把读取的信息填写到对应的栏目中,这些都不困难,大概使用ChatGpt+Github CoPilot有多半天就完成了。唯独到了自动识别和录入验证码这步,耗费了大概2周,主要问题:1、怎么识别;2、如何把验证码下载到本地

针对第一个问题,我一开始本来想自己识别,用ChatGpt+Github CoPilot很多方法,

例如:

    # 使用验证码识别方法识别验证码,替换为实际的验证码识别方法
    captcha = recognize_captcha('captcha.png')

但都识别的很差,最后突然想到了以前自己曾经用过华为云的OCR识别营业执照的功能,就想到了能不能用华为云的API接口,查询了一下果然可以使用,于是就开通了这个OCR通用识别文字的功能,成功调用一次0.08元,300嘛也就24块钱,如果能省下我6个小时的时间,很值了。因为各个云都有代码示例,所以这步解决了。这步的重点是想到有这样的方法。

针对第二个问题,用ChatGpt+Github CoPilot大都给到的是这个方法,例如:

    # 获取验证码图片地址并下载
    captcha_image_url = driver.find_element(By.ID, 'captcha_image').get_attribute('src')  # 替换为实际的验证码图片元素定位方式
    response = requests.get(captcha_image_url)
    with open('captcha.png', 'wb') as f:
        f.write(response.content)

然而每次验证码和实际的都不一样,想了半天,问题就出现在request .get请求上。突然想明白了,因为每次你做request.get 请求都会把验证码换一个新的,所以你下载的是最新的,但是浏览器上并不是最新的验证码,所以怎么识别也录入不对。在这上面我大概花费了5-8天的时间。

最后突然想到了,我为什么不用find_element(By.ID)的方法,把这个图片下载下来呢?就是这样:

    #获取验证码下载到本地
    captcha_input_img = driver.find_element(By.ID, 'captchaImg')  # 验证码
    captcha_input_img.screenshot('D:\captcha11.png')

最后解决了这个问题,真不容易,尽管OCR识别验证码还有一些不准确,但是至少跑通了。

希望我的经验可以帮到更多的人。 


下面是完整代码供大家参考

import openpyxl
import requests
from PIL import Image
from bs4 import BeautifulSoup
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 base64
from huaweicloudsdkcore.auth.credentials import BasicCredentials
from huaweicloudsdkocr.v1.region.ocr_region import OcrRegion
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkocr.v1 import *
import ocrimage
import io

# 加载Excel表格
wb = openpyxl.load_workbook('实际文件路径')
sheet = wb.active

# 创建WebDriver对象
driver = webdriver.Chrome()

# 打开查分网站
headers = {"user-agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0'}
driver.get('实际网址')  # 替换为实际的查分网站链接
# 等待页面加载完成,直到指定元素可见
wait = WebDriverWait(driver, 10)  # 设置最大等待时间为10秒
# 循环读取Excel表格中的考生号和身份证
for row_number, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
    examNo_id, examinneNo_id,idcard_id = row[0], row[1],row[4]
    #截取idcard_id的后6位
    idcard6_id = idcard_id[-6:]
    # 输入考生号和身份证
    examNo_input = driver.find_element(By.ID, 'examNo')  # 准考证号
    examinneNo_input = driver.find_element(By.ID, 'examinneNo')  # 考生号
    idcard_input = driver.find_element(By.ID, 'idCard')#idCard身份证号
    captcha_input = driver.find_element(By.ID, 'captcha')  # 验证码
    #准考证号
    examNo_input.clear()
    examNo_input.send_keys(examNo_id)
    #考生号
    examinneNo_input.clear()
    examinneNo_input.send_keys(examinneNo_id)
    #身份证后6位
    idcard_input.clear()
    idcard_input.send_keys(idcard6_id)
    #获取验证码下载到本地
    captcha_input_img = driver.find_element(By.ID, 'captchaImg')  # 验证码
    captcha_input_img.screenshot('实际路径')
    # 优化图片
    def preprocess_image(image):
        # 灰度化
        image = image.convert('L')
        # 二值化
        threshold = 152  # 二值化阈值
        image = image.point(lambda x: 0 if x < threshold else 255, '1')
        return image
    # 把保存在本地的验证码图片转换为jpg格式
    image = Image.open('实际路径')
    preprocess_captcha_image_jpg = preprocess_image(image)
    image = preprocess_captcha_image_jpg.convert('RGB')
    image.save('实际路径')
    #调用华为OCR识别验证码
    ak = "自己的ak"
    sk = "自己的sk"
    credentials = BasicCredentials(ak, sk)  # 构造鉴权对象
    client = OcrClient.new_builder() \
        .with_credentials(credentials) \
        .with_region(OcrRegion.value_of("cn-north-4")) \
        .build()

    # 读取图片转64位编码
    def encode_image(origin_image):
        with io.BytesIO() as buffer:
            origin_image.save(buffer, format="JPEG")
            return base64.b64encode(buffer.getvalue()).decode()
    # 识别图片
    try:
        request = RecognizeGeneralTextRequest()
        #从本地读取图片
        captcha_image_jpg = Image.open('实际路径')
        image64=encode_image(captcha_image_jpg)
        request.body = GeneralTextRequestBody(image=image64)
        response = client.recognize_general_text(request)
        response_dict = response.to_dict()
        words_block_list = response_dict.get('result', {}).get('words_block_list', [])
        if words_block_list:
            captcha_text = words_block_list[0]['words']
            print(captcha_text)
        else:
            print("No text found in image.")
    except exceptions.ClientRequestException as e:
        print(e.status_code)
        print(e.request_id)
        print(e.error_code)
        print(e.error_msg)

    # 输入验证码
    captcha_input.clear()
    captcha_input.send_keys(captcha_text)

    # 提交表单
    #submit_button = driver.find_element_by_xpath('//input[@id="queryBtn"]') # 替换为实际的提交按钮元素定位方式
    submit_button = driver.find_element(By.ID, 'queryBtn')  # 替换为实际的提交按钮元素定位方式
    submit_button.click()

    WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.ID, 'result_content')))  # 替换为实际的成绩表格元素定位方式
    # 解析成绩页面并获取成绩信息

    soup = BeautifulSoup(driver.page_source, 'lxml')  # 使用更快的解析器lxml
    score_table = soup.find('table', {'class': 'case'})  # 使用字典形式的参数传递,定位方式更清晰
    # 提取各科目成绩,根据实际网页结构提取相应的数据
    scores = score_table.find_all('td', {'class': 'title_p'})  # 使用find_all()函数,避免重复定位
    #获取scores标签信息中的语文、数学、英语成绩
    chinese_score = scores[0].find_next_sibling('td').text.strip() #语文成绩
    math_score = scores[2].find_next_sibling('td').text.strip() #数学成绩
    english_score = scores[4].find_next_sibling('td').text.strip()#英语成绩
    physics_score = scores[6].find_next_sibling('td').text.strip()#物理成绩
    history_score = scores[8].find_next_sibling('td').text.strip()#历史成绩
    geography_score = scores[10].find_next_sibling('td').text.strip()#地理成绩
    total_score = scores[12].find_next_sibling('td').text.strip()#总成绩
    # 将成绩写入Excel表格

    sheet.cell(row=row_number, column=7, value=chinese_score)
    sheet.cell(row=row_number, column=8, value=math_score)
    sheet.cell(row=row_number, column=9, value=english_score)
    sheet.cell(row=row_number, column=10, value=physics_score)
    sheet.cell(row=row_number, column=11, value=history_score)
    sheet.cell(row=row_number, column=12, value=geography_score)
    sheet.cell(row=row_number, column=13, value=total_score)

    # 点击返回按钮,返回到查询页面
    submit_button = driver.find_element(By.ID, 'backBtn')  # 替换为实际的提交按钮元素定位方式
    submit_button.click()
# 保存Excel表格
wb.save('实际路径')

# 关闭WebDriver
driver.quit()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值