爬虫中使用第三方打码平台(识别验证码)

引入

在爬虫程序中,常常会遇到验证码校验的关卡,人工识别不仅慢而且很费精力,使用打码平台就成了高效,省时且便利的选择。

本次案例对于高清资源库1080zyk.com进行爬虫采集,使用超级鹰验证码识别(chaojiying.com)和python的requests库具体实现,类似的第三方打码库还有云打码,tt图鉴ddddorc库等

代码实现

在这里插入图片描述
首先我们对网页进行分析,通过键入搜索框,并点击搜索按钮,F12中的网络接口可以找到,发起了两次请求

  • post请求,将搜索框里的内容通过表单数据data发送给服务器

在这里插入图片描述

  • get请求,返回的是验证码的图片

在这里插入图片描述

所以我们先编写如下代码,将图片保存本地,使用Session对象是为了保证验证码和请求是同一次会话

import requests

# 爬取优质资源网
session = requests.Session()

urls = {
    "data": "http://www.1080zyk.com/index.php?m=vod-search",
    "yanzenma": "https://www.1080zyk.com/inc/common/code.php?a=search&s=",
}

for key, url in urls.items():
    if key == "data":
        data = {"wd": "python", "submit": "search"}
        response = session.post(url, data=data)
        print(response.text)
    elif key == "yanzenma":
        response = session.get(url)
        # response是一张图片
        with open("./yanzenma.jpg", "wb") as f:
            f.write(response.content)
        print("验证码已保存到yanzenma.jpg")

超级鹰平台的使用

然后登陆到超级鹰打码平台,下载相应语言的接口示例

在这里插入图片描述

把python源文件解压到项目目录下,修改里面的参数,自己去超级鹰网站生成软件id,填入替换96001

在这里插入图片描述

在这里插入图片描述

导入类

在你的爬虫文件中导入超级鹰类,替换参数和图片地址,原本打印出来的是一个字典,我们取他的pic_str

在这里插入图片描述

可以看到,最后获取到了正确的验证码值

JavaScript逆向

在这里插入图片描述

检查验证码页面,发现主要内容是一段js代码实现检验功能,于是,我们把这段代码给复制下来,交给fittencode解释.

fittenCode插件

结果如下:

$(".ldg_verify_submit").click(() => {
            const code = $(".mac_verify").val();
            const type = $("#code_type").val();
            $.get("/inc/ajax.php?ac=code_check&code=" + code + "&type=" + type + "&rnd=" + Math.random(), function (r) {
                const data = JSON.parse(r);
                if (data.code == 1) {
                    location.reload();
                } else {
                    alert(data.msg);
                }
            });
        })
帮我解释一下这段代码

这段代码是一个使用jQuery编写的JavaScript代码片段,主要功能是处理一个验证提交按钮的点击事件。以下是对这段代码的详细解释:

  1. $(".ldg_verify_submit").click(() => { ... })

    • 这行代码监听类名为ldg_verify_submit的元素的点击事件。当该元素被点击时,执行箭头函数内的代码。
  2. const code = $(".mac_verify").val();

    • 这行代码获取类名为mac_verify的元素的值,并将其存储在变量code中。通常,这个元素可能是一个输入框,用户在这里输入验证码。
  3. const type = $("#code_type").val();

    • 这行代码获取ID为code_type的元素的值,并将其存储在变量type中。这个元素可能也是一个输入框或下拉菜单,用于选择验证码的类型。
  4. $.get("/inc/ajax.php?ac=code_check&code=" + code + "&type=" + type + "&rnd=" + Math.random(), function (r) { ... })

    • 这行代码使用jQuery的$.get方法发送一个GET请求到服务器。请求的URL是/inc/ajax.php,并附带以下查询参数:
      • ac=code_check:表示执行的操作是验证码检查。
      • code= + code:传递用户输入的验证码。
      • type= + type:传递验证码的类型。
      • rnd= + Math.random():添加一个随机数,以避免浏览器缓存。
  5. const data = JSON.parse(r);

    • 这行代码将服务器返回的JSON字符串解析为JavaScript对象,并存储在变量data中。
  6. if (data.code == 1) { location.reload(); } else { alert(data.msg); }

    • 这行代码检查解析后的data对象中的code属性。如果code等于1,表示验证成功,页面将重新加载(location.reload())。如果code不等于1,表示验证失败,弹出一个警告框显示data.msg中的错误信息(alert(data.msg))。

总结来说,这段代码的功能是当用户点击验证提交按钮时,获取用户输入的验证码和验证码类型,然后通过AJAX请求将这些信息发送到服务器进行验证。根据服务器的响应,决定是重新加载页面(验证成功)还是显示错误信息(验证失败)。

于是我们将参数拼接,对https://www.1080zyk.com/inc/ajax.php?ac=code_check&code=3991&type=search&rnd=1发起请求,最后得到响应数据为{"code":1,"msg":"ok"},然后reload页面,发现,可以正常获得响应,于是,补充下列代码
在这里插入图片描述

# 校验验证码url
url = f"http://www.1080zyk.com/inc/ajax.php?ac=code_check&code={code}&type=search&rnd={random.randint(100000, 999999)}"

response_code = session.get(url)
if response_code.json()["code"] == 1:	# 注意,不是字符串1
    print("验证码正确")
    print(session.get(urls["data"]).text)
else:
    print("验证码错误")

最后,加入选择下载项和保存本地的代码,就完成了

import random
import requests
import lxml.etree
from 超级鹰接口 import Chaojiying_Client

# 初始化会话
session = requests.Session()

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0",
    "Cookie": "_ga=GA1.1.838502423.1724576396; PHPSESSID=o15hha1hpqlbddfon13h85rt37; _ga_20DNV0Q96J=GS1.1.1724591590.4.1.1724591970.0.0.0",
}

urls = {
    "data": "http://www.1080zyk.com/index.php?m=vod-search",
    "yanzenma": "https://www.1080zyk.com/inc/common/code.php?a=search&s=",
}


def fetch_captcha():
    response = session.get(urls["yanzenma"])
    with open("./yanzenma.jpg", "wb") as f:
        f.write(response.content)
    print("验证码已保存到yanzenma.jpg")


def recognize_captcha():
    chaojiying = Chaojiying_Client(
        "","",1
    )  # 用户中心>>软件ID 生成一个替换 96001
    im = open(
        "./yanzenma.jpg", "rb"
    ).read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
    result = chaojiying.PostPic(im, 1902).get(
        "pic_str"
    )  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
    return result


def verify_captcha(code):
    url = f"http://www.1080zyk.com/inc/ajax.php?ac=code_check&code={code}&type=search&rnd={random.randint(100000, 999999)}"
    response_code = session.get(url)
    return response_code.json()


def search_data():
    data = {"wd": "你好", "submit": "search"}
    response = session.post(urls["data"], data=data)
    return response.text


def parse_data(html):
    tree = lxml.etree.HTML(html, None)
    base_xpath = "//div[@class='xing_vb']/ul/li"
    items = tree.xpath(base_xpath)

    nums = [
        {"标题": 1, "类别": 2, "地区": 3, "评分": 4, "更新时间": 5},
        {
            "链接": "span[2]/a/@href",
            "标题": "span[2]/a/text()",
            "类别": "span[3]/text()",
            "地区": "span[4]/text()",
            "评分": "span[5]/text()",
            "更新时间": "span[6]/text()",
        },
    ]

    index = 1
    for item in items:
        if index == 1:
            for name, num in nums[0].items():
                name_value = item.xpath(f"./span[{num}]/text()")[0]
                print(name_value)
            index += 1
        else:
            for name, path in nums[1].items():
                name_value = item.xpath(f"./{path}")[0]
                print(name_value)


def main():
    fetch_captcha()
    # code = recognize_captcha()
    code = input("请输入验证码:")
    result = verify_captcha(code)
    if result["code"] == 1:
        print("验证码正确")
        html = search_data()
        parse_data(html)
    else:
        print("验证码错误")


if __name__ == "__main__":
    main()

后面发现,js中使用reload刷新页面,一开始没注意,所以使用简单的requests库满足不了,可以改用selenium操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0zxm

祝大家天天开心

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值