Loading

自动取关微博账号用户 && 删除已发微博

通过 API 删除微博、取消关注用户。

用到的工具

  • Requests:发送 API 请求
  • Requests-html:解析网页,提取值
  • CSS 定位、XPath 定位或正则,都可
  • Chrome Network 抓包

都是一些基础用法,没啥难度,算是一个小练习吧。

准备工作

第一步是获取登录凭证。

打开谷歌浏览器,进入微博网页移动版(weibo.cn),登录自己的账号。按 F12 进入开发者工具,点击 Network 开启抓包,刷新页面,在 API 请求头内,把 cookie 内容复制下来。

image-20220506113334605

第二步抓取参数 st 的值。

首页 -> 关注,到达关注列表页面,用箭头定位到【取消关注】元素,该元素的 href 属性链接内就包含 st 的值,记录一下。

流程分析

以取消关注为例,删除微博同理。

开启抓包,手动取消关注一个用户,得到请求如下:

https://weibo.cn/attention/del?rl=1&act=delc&uid=5623715908&st=e08ff9
  • rl:代表什么意思暂时不知道,当取消关注其他用户时,该值不变,证明可复用;
  • act:按字面意思,应该是操作类型,表示删除的动作,该值不变;
  • uid:要取消关注的用户的 ID,定位到该元素,发现在 href 元素内包含该参数,可以通过脚本实时获取;
  • st:与上面我们抓到的是一样的,当取消关注其他用户时,该值不变,证明可复用。

初步分析完成后,程序的大致流程也就出来了:

  • 进入网页,登录
  • 进入关注列表页面,获取分页总数
  • 遍历分页总数次,获取每页用户信息
  • 遍历每个用户,提取到 uid
  • 执行取消关注请求

脚本编写

首先做一些初始化工作,比如请求链接拼装、实例变量初始化、获取当前登录用户信息。

class WeiBo:

    HOST = "https://weibo.cn"
    USER_AGENT = ""

    def __init__(self, uid, flag=1):
        self.headers = {
            'user-agent': self.USER_AGENT,
            'cookie': COOKIES
        }
        self.session = HTMLSession()
        self.session.headers = self.headers

        self.uid = str(uid)
        self.flag = int(flag)  # 1 删除全部微博;2 取消全部关注
        self.total_weibo_pages = 0   # 已发表微博总页数,每页 10 条
        self.total_follow_pages = 0  # 已关注用户总页数,每页 10 个

        # URL
        self.url_info = f"{self.HOST}/{self.uid}/info"
        self.url_profile = f"{self.HOST}/{self.uid}/profile"  # Default page=1
        self.url_del_weibo = f"{self.HOST}/mblog/del"
        self.url_follow = f"{self.HOST}/{self.uid}/follow"
        self.url_del_follow = f"{self.HOST}/attention/del"

        # 用户信息,从 profile 获取
        self.post = 0  # 发表微博数
        self.follow = 0  # 关注人数
        self.fans = 0  # 粉丝人数

        # 初始化
        self.get_weibo_list_page()
        self.get_user_info()

实现方法:需包含两个功能,获取关注总页数、根据页数获取该页所有用户信息。

def get_follow_list_page(self, page=1):
    """ 根据页数获取我的关注页面的内容
        [<Element>, ...]
    """
    r = self.session.get(self.url_follow, params={"page": page})
    html = r.html
    # 获取总页数
    if self.total_follow_pages == 0:
        page_nums_str: str = html.find("div.pa", first=True).text
        self.total_follow_pages = int(page_nums_str.split("/")[-1].replace("页", ""))
    # 获取被关注人对象(每页最多 10 个)
    follow_objs = html.find("table tr")
    return follow_objs

实现方法:根据单个用户,提取到UID

def get_single_uid(self, user_obj: Element):
    """获取被关注用户 ID"""
    uid = None

    elements = user_obj.find("a")
    name = elements[1].text
    for e in elements:
        link = e.attrs["href"]
        if "uid" in link:
            params = link.split("?")[-1].split("&")
            for p in params:
                if "uid" in p:
                    uid = p.split("=")[-1]
                    break

    logger.info(f"当前被关注用户为: {name}({uid})")
    return uid

实现方法:根据UID,取消关注。

def del_single_follow(self, uid):
    """取消关注, uid 为被关注用户的 ID"""
    headers = {
        **self.headers,
        **{"referer": self.url_del_follow + f"?uid={uid}&rl=1&st={ST}"}
    }
    params = {
        "rl": "1",
        "act": "delc",
        "uid": uid,
        "st": ST
    }
    r = requests.get(self.url_del_follow, params=params, headers=headers)
    # logger.debug(r.url)
    # logger.debug(r.text)
    if r.status_code == 200 and "首页" not in r.text:
        logger.success(f"取消关注成功: {uid}")
        return True
    return False

将上面实现的方法,组装一下,通过遍历完成取消全部关注的功能。

def del_all_follow(self):
    """取消全部关注"""
    self.get_follow_list_page()  # 获取关注总页数
    del_nums = 0  # 取消关注数统计

    for i in range(1, self.total_follow_pages):
        logger.info(f"******* 取消关注,第 {i} 页 *******")
        objs = self.get_follow_list_page(page=i)

        for obj in objs:
            uid = self.get_single_uid(obj)
            if self.del_single_follow(uid):
                del_nums += 1
                logger.info(f"取消关注总人数为: {del_nums}.\n")
                sleep(sec)

运行程序,会输出基本信息。

image-20220506121358689

此时,访问网页版,关注人数会实时减少,证明程序功能正常。

实际运行过程中, 当请求100+次后,会被限制访问一段时间。

最无语的是,还剩最后 20 个关注,触发了风控策略,关注列表不返回内容。不过还好,总体上达到预期,给我省了不少功夫。

使用微博客户端过程中,还发现了一些体验不好的情况,比如微博手机客户端我的页面,不支持下拉刷新;已经取关的用户,依然在微博-关注里面展示动态;还有大半屏的消息通知开关...好复杂。

只是一个普通用户,了解的不多,吐槽太片面,哈哈。

最后,源码地址:
https://github.com/abeelan/ha-ha

posted @ 2023-03-08 14:34  ABEELAN  阅读(47)  评论(0编辑  收藏  举报