Python爬虫 - 02.实现贴吧签到

前面的文章《Python爬虫 - 01.实现贴吧一键签到》实现了贴吧一键签到,但是贴吧一键签到的功能有很多限制,每天只能一点后才能用,而且一次只能签到50个吧,所以我们换一种思路避开这些限制,实现随时随地签到

一、分析

我们要先获取到关注的贴吧列表信息,然后逐一进行签到

  1. 获取贴吧关注列表
  2. 获取贴吧签到的接口信息
  3. 遍历贴吧列表,发送请求进行签到

二、获取贴吧关注列表

获取贴吧关注列表有几种方法可以实现

  1. 通过baidu贴吧提供的功能"我的贴吧",从HTML中提取到贴吧列表信息
  2. 从贴吧首页中去提取关注列表信息

第一种比较麻烦,如果页数比较多发送的请求也相应增多,还需要解析HTML,效率低下,而且信息量没有那么全面
所以我推荐用第二种

打开贴吧首页,按F12打开浏览器开发者工具,选择网络标签。在贴吧首页中,我们可以看到 爱逛的吧下面就是你的关注列表,但这个关注列表由于只显示部分吧,剩下的被隐藏了,我们把鼠标放到查看更多上,剩下的就会显示出来,这里要观察开发者工具中网络的变化,发现并没有发送网络请求,说明这些数据不是通过AJAX请求拿到的,而是在网页加载的时候就是已经加载到了过来了。

在这里插入图片描述

下面我们分别从HTML,JS以及本地存储中查找这个关注列表的信息
首先从HTML中查找,选择查看器,首先定位到这个查看更多弹出的组件,这个组件有个标题是常逛的吧,按Ctrl+F搜一下这个标题,有两个结果,第二个就是这个组件,里面的内容包含了隐藏的贴吧列表信息,这样我们可以通过解析HTML拿到关注贴吧的列表。
在这里插入图片描述
除了这种解析HTML的方法,是否还有其他方法呢?答案是有,查找JS信息
首先我们拿到一个吧的id,搜data-fid即可,例如我关注的帝吧(李毅吧),id为59099,我们在查看器中搜索59099,会出来3个结果,排除掉HTML标签,剩下两个是包含在script中的内容,把他们复制出来分析一下
第一个script中的内容格式化后如下

_.Module.use('spage/widget/forumDirectory',{
    "forums": [
        {
            "user_id": 38947xxx,
            "forum_id": 59099,
            "forum_name": "\u674e\u6bc5",
            "is_like": 0,
            "is_black": 0,
            "like_num": 0,
            "is_top": 0,
            "in_time": 1632026524,
            "level_id": 10,
            "level_name": "\u62a0\u811a\u5927\u6c49",
            "cur_score": 2474,
            "score_left": 526,
            "is_sign": 0
        },
        //...
        //...
    ],
    "directory": {...}
})

第二个script中的内容如下:

_.Module.use("spage/widget/AsideV2",
[
    [
        {
            "user_id": 38947xxx,
            "forum_id": 59099,
            "forum_name": "\u674e\u6bc5",
            "is_like": 0,
            "is_black": 0,
            "like_num": 0,
            "is_top": 0,
            "in_time": 1632026524,
            "level_id": 10,
            "level_name": "\u62a0\u811a\u5927\u6c49",
            "cur_score": 2496,
            "score_left": 504,
            "is_sign": 1
        },
        //...
        //...
    ]
])

从上面两段内容,我们可以看出,这脚本中的数据就是贴吧关注列表的信息,包含了贴吧id,名字,经验,是是否签到等信息,只要把这其中的列表提取出来即可,上面两个任意一个都可以,因为他们的数据 是相同的。

三、获取贴吧签到的接口信息

点进一个贴吧,按F12打开开发者工具,然后点击签到就拿到了这个签到接口
在这里插入图片描述

接口地址:

https://tieba.baidu.com/sign/add

这是一个POST请求,带有三个请求参数

{
'ie': 'utf-8',
'kw': 'python',
'tbs': '222b0543ebe394f916324xxxxx'
}

这三个参数分别是编码,贴吧的名字和一个tbs参数,tbs参数上一篇已经说过如何提取,这里就不重复了。

没看过的上一篇文章的朋友可以先去看一下,传送门:《Python爬虫 - 01.实现贴吧一键签到》

tbs参数是可以重复使用的,只要我们拿到一个即可,不用每个请求都要重新拿一次新的值

四、编码实现

下面开始编码实现

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''
实现百度贴吧签到
API: 
一键签到 POST https://tieba.baidu.com/tbmall/onekeySignin1
逐个签到 POST https://tieba.baidu.com/sign/add

注意事项:
1、百度贴吧0点到1点是不能够使用一键签到的,所以要逐个贴吧进行签到
'''
__author__ = "Conca"

import requests
import re
import time
import json
import random

# 请求头信息,定义为全局方便重用
headers = {
    "User-Agent": "Firefox/92.0", # 替换为你的UA
    "Referer": "https://tieba.baidu.com/",
    "Cookie": "your cookie xxxxxxxxxxxxxx", # 替换为你的cookie
}

# 从HTML中获取tbs参数和贴吧关注列表
def getTiebaInfo():
    try:
        url = "https://tieba.baidu.com/"

        # 发送请求,下载贴吧HTML页面
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        response.encoding = response.apparent_encoding

        html = response.text

        # 从HTML中提取tbs参数
        tbs = getTbs(html)

        # 从HTML中提取贴吧关注列表
        forums = getAllForums(html)

        return {"forums": forums, "tbs": tbs}
    except Exception as e:
        print("获取贴吧数据失败,原因:", e)
        return None

# 用正则表达示从HTML中提取参数 tbs 的值
def getTbs(html):
    # 正则表达式学得不太好,用得有点呆板,凑合用
    match = re.search(r'PageData.tbs = "(.*)";PageData.is_iPad', html)
    if match:
        tbs = match.group(0).split('"')[1]
        return tbs
    return None


# 获取关注的贴吧列表
def getAllForums(html):
    #  _.Module.use('spage/widget/forumDirectory', {"forums": [...],"directory": {}})
    match = re.search(r'{"forums":\[.*\],"directory"', html)
    if match:
        data = match.group(0)
        forums = json.loads(data[data.find('['):data.rfind("]")+1])
        return forums
    return None


# 逐个吧签到
def tiebaSigninOneByOne(tiebaInfo):
    # 签到接口
    signin_url = "https://tieba.baidu.com/sign/add"
    tbs = tiebaInfo.get("tbs")

    # 统计结果
    success_count = 0
    fail_count = 0

    # 签到
    for forum in tiebaInfo.get("forums"):
        # 跳过已经签到的贴吧,减少请求次数,防止验证码
        is_sign = forum.get("is_sign")
        if is_sign == 1:
            continue

        # 构建请求数据
        forum_name = forum.get("forum_name")
        sigin_data = {
            "ie": "utf-8",
            "kw": forum_name,
            "tbs": tbs,
        }

        try:
            # 发送请求签到
            response = requests.post(
                url=signin_url, data=sigin_data, headers=headers)
            response.raise_for_status()
            response.encoding = response.apparent_encoding

            content = response.json()

            # 判断签到结果,打印消息
            if content.get("no") == 0:
                success_count += 1
                print("{}吧签到成功".format(forum_name))
            else:
                fail_count += 1
                print("{}吧签到失败,失败原因:{}".format(
                    forum_name, content.get("error")))
        except Exception as e:
            fail_count += 1
            print("Error: {}吧签到发生错误,{}".format(forum_name, e))

        # 随机睡眠1-5秒,防止弹验证码,自动化不追求速度,一切求稳
        second = random.randint(1, 5)
        time.sleep(second)

    print("本次签到成功%d个,失败%d个" % (success_count, fail_count))


# 主方法
def main():
    print("-----------百度贴吧开始签到-------------")
    tiebaInfo = getTiebaInfo()
    if tiebaInfo:
        tiebaSigninOneByOne(tiebaInfo)
    else:
        print("签到失败")
    print("-----------百度贴吧签到结束-------------")


if __name__ == "__main__":
    main()

到此就实现了贴吧签到的功能

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值