0%

免登录新浪微博爬虫系列之第一篇 单博主微博及评论数据

我的 GITHUB 地址:https://github.com/xiaosimao/weibo_spider 2017.05.04 更新: 感谢哥本哈根小树对于获取 containnerid 的指教,多谢。

大家好,我是新人四毛,大家可以叫我小四毛,至于为什么,在家排行老四,农村人,就是那么任性。

好,自我介绍完毕,开始今天的学(zhuang)习(bi)之路。

说明:本文针对的是有一些爬虫基础的同学,所以看不太懂的同学先补一下基础。

本文的全部代码并没有上传到 GITHUB 中,而且本文的 code 部分给出的代码也是指导性的,大部分还是要靠大家自己动手完成。待后几篇博客出来以后,代码会放到上面。

大家如果有问题交流的话,欢迎在下面进行评论,或者可以加我 QQ:549411552(加的话麻烦注明来自静觅),欢迎大佬拍砖指错,大家共同进步。

前几天,大才发布了一个视频,主要讲的是通过维护一个新浪微博 Cookies 池,抓取新浪微博的相关数据,爬取的站点是 weibo.cn。相关的代码在大才的 Github 里【大才的视频教程真的很用心,视频高清无码,希望大家可以支持大才,毕竟写了那么多精彩的教程真心不易】。

然而,如果你只是想简单的搞点数据,对技术一点兴趣都没有,又或者某宝搜来搜去都没有买到账号,又或者装个模拟登陆需要的模块都想跳楼,有没有除此之外其他的办法呢?你有没有想过在免登陆的情况下就可以获得你想要的数据呢?如果你这么想过而又没有做出来,那么接下来,让我们一起搞(qi)事(fei)吧。

本文重点提供解决问题的思路,会把最关键的点标示出来,代码基本没有。有什么不对或不足之处,还望大家指出,共同进步。

1.前期准备

代理 IP。虽说本文介绍的方法不需要 Cookies,但是代理 IP 还是需要的,要不然也是被新浪分分钟的 403(我测试的时候会出现)。如果你连 403 都不知道是什么,那么还是去看看大才的爬虫基础课程,或者不想看文字的话直接来报大才的视频课程课,哈哈(大才,今晚得加两个菜啊,我这吆喝的)。

2.思路分析

一般做爬虫爬取网站,首选的都是 m 站,其次是 wap 站,最后考虑 PC 站。当然,这不是绝对的,有的时候 PC 站的信息最全,而你又恰好需要全部的信息,那么 PC 站是你的首选。一般 m 站都以 m 开头后接域名,试一下 就好了,实在找不到,上网搜。

所以本文开搞的网址就是 m.weibo.cn。但是当你在浏览器中输入这个网址时,你得到的应该是下面这个页面,如果不是,说明你的浏览器保留了你最近登录微博的 cookie,这个时候,清空浏览器保存的数据,再次打开这个网页,就应该也是这个界面了:

我滴天,是的,你没看错,就是这个登录界面。你不是说不需要登录吗?怎么 TM 的还是这个万恶的界面?怎么破?WTF?

哈哈,其实一开始我也不知道,后来经人指点,才发现只要在后面加入一些东西之后就不会看到这个界面了。那么是什么呢?

当当当当!!!!!!!!!!

http://m.weibo.cn/u/1713926427

当你看到这个网址的时候,憋说话,一定要用心去感受,这个时候说话你的嘴都是咧着的,别问我为什么知道,我就是知道。

用心去感受,真的。

对了,上面网址最后的数字是博主的数字 ID,在 weibo.com 的源码里可以找到,这里不做说明了。

打开上述网址, 界面变成这个样子,是不是很厉害的样子(大手勿喷),拨云见日,对于老手来说,下面的他们就可以不看了,可以去抓包写代码了,但是对于一头雾水的小伙伴请接着往下看:

这就是本文爬虫的入口,没错,就说牛逼的榜姐,入口选一些质量高的,比如你想爬新闻方面信息,那么你就去找澎湃新闻,新浪新闻之类的。

通过该入口,我们可以抓取该博主的所有微博及评论信息,以及该博主关注的人的微博及评论信息,依次往后,循环不断。

在这里谈一点经验:

其实做爬虫,最基础的当然是写代码的能力,抓包什么的都不是什么困难的事,抓包很简单很简单。我觉得最难的是找到入口,找到一个最适合的入口。怎么定义这个最适合呢?就是要去尝试,依照一般的顺序,先找找 M 站,再找找 wap 站,最后再去看 PC 站,找到一个合适的入口,往往会事半功倍。前几天抓取途牛网的相关游记信息,爬 PC 站分分钟的 302,但是爬 M 站,全是接口,全程无阻。

因大多数人都是采集微博信息以及评论信息,所以下面将以这两方面为主。

剧透一下,在这里可以抓到的信息:

(1) 博主信息 (没发现有价值的信息,下面抓包过程不讲)

(2) 博主微博信息(下文抓包讲解)

(3) 微博评论信息(下文抓包讲解)

(4) 热门微博信息(小时榜,日榜,周榜,月榜)(下文抓包未讲解,大家可以摸索一下)

。。。。。。还有很多我没有细看,等待各位细细研究吧。

3. 抓包分析

首先,得会抓包,一般的浏览器的 Network 够用了。

(1) 微博正文抓包

点击 上图中的微博然后往下拉,抓包出现下图:

分析:

可以看到,服务器返回的数据为 json 格式,这个是做爬虫的最喜欢的了。返回的数据包括很多的字段,图中也以及做了标示,相信大家都能看的懂,看不懂那也没办法了。

最后放上抓包的数据:

  1. Request URL:

    http://m.weibo.cn/api/container/getIndex?type=uid&value=1713926427&containerid=1076031713926427&page=2

  2. Request Method:

    GET

  3. Query String Parameters

    type: uid

    value: 1713926427

    containerid: 1076031713926427

    page: 2

(2) 微博评论抓包

单击微博内容,就可以抓包成功,如下图:

分析:

从上面可以看出,这里的数据依然还是很好获取的。

最后放上抓包的数据:

  1. Request URL:

    http://m.weibo.cn/api/comments/show?id=4103388327019042&page=1

  2. Request Method:

    GET

  3. Query String Parameters

    id: 4103388327019042

    page: 1

再次分析:

通过抓包的数据可以发现,获取微博评论必须首先获得这条微博的 ID。所以,目前还是要对微博正文的抓包过程进行分析。

4. 思路解析

在上面的微博正文中发现需要提交以下数据:

type: uid

value: 1713926427

containerid: 1076031713926427

page: 2

其中:type(固定值)、value(博主微博 ID)、containerid(意义不明确,但是带了个 id 在里面,应该代表的是一个唯一性的一个标识)、page(页码)。页码在返回的数据中可以获得。

那么分析到这里,containerid 就是我们要找的最重要的信息。这个字段信息是不会凭空出现的,肯定产生于某一个请求之中,所以这时候,我们再回到开头,回到我们的初始。刷新入口网址,抓包发现了下面 3 个网址,见下图:

分析:

这 3 个网址的格式一模一样,所以点进去看一下里面到底什么情况。

下面的先点开网址 1看看:

分析:

从返回的数据中,可以看到第 1 个网址的主要内容为 user_Info,即博主的个人信息,相关的字段在图中已经标示出来。最令人惊喜的是查找我们需要的 containerid 时,发现数据竟然就在其中,那么可以肯定我们需要的 containerid 就是在这个请求的返回值中,那么问题再次出现,这个请求的网址中又出现了一个 containerid,我们似乎又回到了原点,而且在用户的首页抓包中,在这个请求之前,也没有什么有意义的请求了,到这里是不是就进入死胡同了呢?其实不然,在这里我们就要进行多方面的尝试了,当我们将第一个网址中的 containerid 删掉以后,重新请求一次,发现返回的依然是这些数据,具体见下图:

分析:

而当我将第三个网址,也就是微博正文的网址中的 containerid 去掉后,返回的数据就是博主的个人信息了,而不是我们需要的微博正文,所以可以肯定第一个网址中的 containerid 并不是必须的,而对于网址 3,这个字段则是必须的。

为了让这个爬虫可以顺着一个初始用户爬取到其他用户的相关信息,甚至全网的信息,那么我们就需要让爬虫自己去添加待爬任务。本文选择的初始用户有 3000 多万的粉丝数,就是人们常说的微博大 V。在做这一类的信息爬取时,我们往往关注的是数据的质量,所以我们选择初始用户的关注用户作为下一级的用户。在下一级中,这些用户将被作为初始用户。这样周而复始,最理想的情况当然就是可以把微博全站的质量还不错的博主的微博以及下面的评论都抓取了。但是在实际的操作过程中会发现微博的用户质量真的是参差不齐,所以我们在筛选后面的用户时,可以加一些限制条件,如用户的粉丝数等等。在这里找寻初始用户关注用户信息的这一过程就省略了,留给大家探索一下,很简单。

所以到这里,我们的整个流程就理清了(单个博主,如需循环,则只需要找到下一级用户的 ID 即可,相信这对于聪明的大家肯定不难的):

请求用户主页网址—>得到 containerid,请求微博正文网址—>保存博文相关信息,取出博文 ID,请求评论网址—>得到评论信息

5. CODE TIME

思路已经理清了,那么下面就是 CODE TIME 了,毕竟:

TALK IS CHEAP,SHOW ME YOUR CODE

本文采用 scrapy 编写,重写个 proxy 中间件,即可实现每一个 request 带一个随机 IP,减少被封禁的概率,同时尽量把重试的次数设置大一些。

想要保存哪些信息,根据自身的业务需求而定,具体的信息,能找到的都可以在每一个请求返回的内容中找到,都是 json 格式的,所以这里的代码只是将上面讲的流程实现了一遍,其他的都没有实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# -*- coding: utf-8 -*-
import scrapy
import json

class SinaSpider(scrapy.Spider):
name = "sina"
allowed_domains = ["m.weibo.cn"]
# root id
first_id = '1713926427'

def start_requests(self):
# to get containerid
url = 'http://m.weibo.cn/api/container/getIndex?type=uid&value={}'.format(self.first_id)
yield scrapy.Request(url=url, callback=self.get_containerid)

def get_containerid(self,response):
content = json.loads(response.body)
# here, we can get containerid
containerid = None
for data in content.get('tabsInfo').get('tabs'):
if data.get('tab_type') == 'weibo':
containerid = data.get('containerid')
print 'weibo request url containerid is %s' % containerid

# construct the wei bo request url
if containerid:
weibo_url = response.url + '&containerid=%s'%containerid
yield scrapy.Request(url=weibo_url, callback=self.get_weibo_id)
else:
print 'sorry, do not get containerid'

def get_weibo_id(self, response):
content = json.loads(response.body)
# get weibo id ,you can also save some other data if you need
for data in content.get('cards'):
if data.get('card_type') == 9:
single_weibo_id = data.get('mblog').get('id')
print single_weibo_id
# here ,if you want to get comment info ,you can construct the comment url just the same as wei bo url

6.总结

本文写到这里就算结束了,我一直信奉授人以鱼不如授人以渔,在这篇文章中,我并没有把全部的代码展示出来,而是通过分析的过程来让大家知道怎么去处理这类问题,在文中也留了好几个可以让大家发挥的地方,如用户关注用户怎么获取?按照关键词搜索的信息怎么抓取?等等。我相信大家通过一步步的抓包以及分析一定可以解决这些问题的。这些问题,在以后的博客中我也会继续更新的。

第一次写这样的博客,感觉还是驾驭不了,还是得多多练习。写博客真的很累,向大才致敬,感谢他无私的为我们奉献了这么多精彩的教程。