专栏首页月小水长微博爬虫重要更新:根据话题爬虫的结果批量化爬评论

微博爬虫重要更新:根据话题爬虫的结果批量化爬评论

要实现这个功能,首先要知道,微博的 mid 和 id 分别是什么?

在公众号以前的一篇文章 微博爬虫综述、错误汇总、Q&A 中,阐述了微博爬虫的不同目标站点之间的差异,并明确了我的微博爬虫的站点策略。

  1. 在 weibo.cn 站点爬取指定话题的微博,爬虫文件名是 WeiboTopicScrapy.py 。
  2. 在 m.weibo.cn 站点指定微博的评论,爬虫文件名是 WeiboSuperCommentScrapy.py。

在这两个站点,就算是同一个用户的同一条微博,其唯一标识也不一样,话题爬虫微博的是诸如 Is0XboARR 这样的形式,看上去是不规则的字符串,通常长度为 9,称之为微博的 mid,而后者是 4467107636950632这样的数字形式Is0XboARR4467107636950632 指向同一条微博)。这样就产生了一个问题,如果我们想要爬取一个话题下的所有微博及其评论,难道要在 weibo.cn 爬完微博后,在 m.weibo.cn 搜每一条微博的文本以定位到该微博在 m.weibo.cn 的 id 吗?这样劳神劳力,完全不符合自动化工作的要求。也许你会问,为什么直接在 weibo.cn 爬取评论呢?问得好:weibo.cn 只能抓取前 100 页 差不多 1000 条评论文本,而 m.weibo.cn 可以抓取几千到几万条评论文本,因噎废食,那可不行。

那怎么办?作为一个程序猿,下意识地想到,mid 和 id 肯定存在某种关联,事实上刚好如此。以Is0XboARR4467107636950632为例,讲诉这种转化逻辑。

  1. Is0XboARR从 后 往 前 按四个字符为一组分组,即Is0XboARR
  2. 将这三组字符(串)转成对应的 62 进制的数字,从前往后拼接起来,就得到对应的数字 id 了。

该部分代码如下:

import execjs
jspython = '''str62keys = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
function int10to62(int10) {
    var s62 = '';
    var r = 0;
    while (int10 != 0) {
            r = int10 % 62;
            s62 = this.str62keys.charAt(r) + s62;
            int10 = Math.floor(int10 / 62);
    }
    return s62;
}
function str62to10(str62) {
    var i10 = 0;
    for (var i = 0; i < str62.length; i++) {
            var n = str62.length - i - 1;
            var s = str62.substr(i, 1);  // str62[i]; 字符串用数组方式获取,IE下不支持为“undefined”
            i10 += parseInt(str62keys.indexOf(s)) * Math.pow(62, n);
    }
    return i10;
}
function id2mid(id) {
    if (typeof (id) != 'string') {
            return false; // id数值较大,必须为字符串!
    }
    var mid = '';
    for (var i = id.length - 7; i > -7; i = i - 7)
    {
            var offset1 = i < 0 ? 0 : i;
            var offset2 = i + 7;
            var num = id.substring(offset1, offset2);
            num = int10to62(num);
            mid = num + mid;
    }
    return mid;
}
function mid2id(mid) {
    var id = '';
    for (var i = mid.length - 4; i > -4; i = i - 4) //从最后往前以4字节为一组读取mid字符
    {
            var offset1 = i < 0 ? 0 : i;
            var len = i < 0 ? parseInt(mid.length % 4) : 4;
            var str = mid.substr(offset1, len);
            str = str62to10(str).toString();
            if (offset1 > 0)
            {
                    while (str.length < 7) {
                            str = '0' + str;
                    }
            }
            id = str + id;
    }
    return id;
}'''
ctx = execjs.compile(jspython) # 编译 js
mid = 'Is0XboARR'
id = ctx.call('mid2id', mid)
print(id)

但是,编写代码转化后,我惊讶地发现Is0XboARR转化成的是4466768535861595,而不是4467107636950632 `,在可以确保代码无误的情况下,我试了 N 个 M 次,没有一组匹配上,一首凉凉送给自己。

在 m.weibo.cn 站点上,一条微博评论的起始 URL 如下:

https://m.weibo.cn/comments/hotflow?id=4467107636950632&mid=4467107636950632

当时吧,就抱着试一试的心态,在浏览器输入了

https://m.weibo.cn/comments/hotflow?id=4466768535861595&mid=4466768535861595

没想到,居然出现了想要的微博的评论,真是山重水复疑无路,柳暗花明又一村。

经过大量测试,我发现这上面两条 URL,内容并不是完全相同,两者评论文本有不同程度的时延,有时前者领先 后者几分钟,有时后者领先前者几分钟,不过我觉着问题不大。猜想是微博评论的一个数据备份同步策略:真实的评论保存在某个未知的数据库中,依次同步到不同的站点,所以有时间差(当然只是猜想,具体还得问内部工作人员…)。

于是,在爬取一个话题的所有微博后,我们可以将那些评论数大于 0 的微博的 mid 批量转成 id,然后新建一个过渡 csv 文件,除了 mid、id 列,新增一个字段 isFinished 用来记录哪些微博的评论已经爬取过,方便出错了可以下次直接从没有爬取评论的第一条微博开始

但是这样必须要解决的一个问题是,必须要知道什么时候一条微博的评论全部抓完,在上个版本的 WeiboSuperCommentScrapy.py 中,程序并没有自动判断什么时候停止?其实很简单,假如评论有 100 页,组装参数 101 页爬取后都是重复的评论,爬到重复的就应该停止了,所以每次爬取一条微博的所有评论时,如果列表中不存在评论的唯一标识 wid,就将 wid 追加 保存到列表中,否则就算该条微博的评论爬取结束.。

本文分享自微信公众号 - 月小水长(inspurer),作者:BuyiXiao

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-22

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python 获取微信好友地区、性别、签名信息并将结果可视化

    本篇博客是itchat库系列的第三篇文章,它主要实现的功能是获取微信好友地区、性别、签名信息并将结果可视化

    月小水长
  • 用户、话题、评论一网打尽,分享一个最强微博爬虫

    微博向来是一个极好的吃瓜圣地,为了获取微博上行行色色的数据,微博相关的爬虫也是层出不穷,因为无论是运营者还是数据分析从业者都或多或少需要微博数据,我的许多朋友也...

    月小水长
  • wxPython+opencv 打造自己的画图板

    参数三: filetypes,比如我上面的设置过滤掉了其他非.jpg、.png文件

    月小水长
  • 微软拥抱 Linux,Windows 10 商店上架 Debian

    贡献开源代码,开放 Linux 系统安装,微软正在向这两个曾经抵触的“敌人”敞开怀抱。继 SUSE 和 Ubuntu 之后,Windows 10 的应用商店刚刚...

    Debian社区
  • 【C语言简单说】六:取模运算符以及变量的扩展

    ┴┴ (╰(`□′)╯( ┴┴ … 这一节我们就来说另外的运算符——取模运算符(说白了跟取余数差不多…<—_-)!!!)

    公众号 碧油鸡
  • 新冠肺炎获正式命名COVID-19,钟南山「希望」疫情4月左右结束,回应「最长潜伏期24天」为个例

    昨晚,世界卫生组织(WHO)召开新一轮会议,探讨有关新冠病毒疫情事宜。会上对新冠病毒肺炎疾病进行了命名,为「COVID-19」,即 coronavirus di...

    机器之心
  • Spark Tungsten in-heap / off-heap 内存管理机制前言

    分析方式基本是自下而上,也就是我们分析的线路会从最基础内存申请到上层的使用。我们假设你对sun.misc.Unsafe 的API有一些最基本的了解。

    用户2936994
  • weex-13-组件textarea使用

    一般像这种用户不能使用的情况下,要将控件背景颜色设置成灰色系列,所以我们就借助伪类,设置一下

    酷走天涯
  • 【ES6基础】解构赋值(destructuring assignment)

    我们经常可以在其他编程语言(如GO语言)中看到多返回值这种特性,因为在很多实际场景中,函数的返回值中,函数的返回值并不只有一个单一的值。ES6之前,并没有可以直...

    前端达人
  • exports和module.exports介绍

    为了让nodejs开发过程中,为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统,模块是Node.js 应用程序的基本组成部分,文件...

    无邪Z

扫码关注云+社区

领取腾讯云代金券