16.1 知乎用户爬虫 - 知乎网站分析
16.1.1 知乎网站初步分析
这一章通过知乎爬虫这个例子,实战前面介绍的知识,并简单介绍如何分析爬取到的数据。为了简单演示,只爬取知乎网站用户的信息,包括用户的姓名(昵称)、一句话介绍、部分详细资料、关注的人数、粉丝数等数据。这些数据能帮助我们分析某些行业有哪些“大 V”。
打开知乎网站,分析一下我们需要的这些信息都在哪些网页及其 URL 的构造特点等。如果直接打开知乎首页,会发现它要求登录才能查看,但不登录也是可以访问知乎内部详细页面的,如周源的知乎页面,如图 16-1 所示。
图 16-1 周源的知乎页面
这个页面显示了用户的姓名(昵称),一句话介绍、详细资料、关注的人数(关注了)、粉丝数(关注者)等,但是没有完全显示详细资料,需要单击“查看详细资料”,才能显示全部的个人资料。显然这是一个动态网页,处理起来可能稍微有些麻烦。不过值得庆幸的是,网页中用户所从事行业或者职位等这些关键的信息是优先显示出来的,那是不是所有人都是这样呢?如果多打开几个人的详细页面,就会发现只要有详细资料,都会优先显示知乎用户所从事的行业和职位,如图 16-2 所示。
图 16-2 知乎的个人页面
这样就省去了处理动态网页加载、查看详细数据的麻烦,只需要爬取个人页面中显示出来的这部分详细资料即可。
为了从一个网页开始爬取整个网站的用户信息,可以利用用户与用户之间的关注和被关注关系,从一个用户开始,爬取他的关注对象和粉丝信息;爬取这些人的信息后,继续这个循环,爬取这些人的关注对象和粉丝信息,一直循环下去,直到爬取整个网站的用户数据。
下面研究一下 URL 的构造特点,以便于使用 CrawlSpider 编写 URL 提取规则。用户个人页面的 URL 形式如下。
https://www.zhihu.com/people/mileijun/activities https://www.zhihu.com/people/Junejin/activities
activities 是动态的意思,如果访问去掉最后面的 activities 的 URL,会发现这个网址会自动跳转回带 activities 的个人动态页,也就是说个人页其实也就是他的个人动态页面。我们既可以请求不加 activities 的个人页 URL,也可以请求加上了 activities 的个人页 URL,效果是完全相同的。如果查看网页中关注对象列表和粉丝列表的用户 URL,就会发现它们指向的 URL 是不加 activities 的,因此可以请求结尾没有 activities 的个人详细页面 URL,请求的 URL 形式如下。
https://www.zhihu.com/people/mileijun
如果用正则表达式来提取关注对象和粉丝的个人 URL,可以采用如下形式。
www.zhihu.com/people/.*
个人详细页面还有回答、文章等很多栏目,其 URL 如下。
https://www.zhihu.com/people/mileijun/answers https://www.zhihu.com/people/mileijun/posts
这些 URL 都满足上面的正则表达式,为了防止抓取这些栏目,可以排除 www.zhihu.com/people/后面包含有 / 的网址,正则表达式可以改为如下形式。
www.zhihu.com/people/((?!/).)*$
再来看一下提取关注对象列表和粉丝列表页 URL 的正则表达式写法。通过观察网址特点,很容易写出这两个正则表达式。
people/.*/following$ people/.*/followers$
这里为什么要使用匹配结尾的符号$呢?因为个人页面还有关注话题、关注专栏等几个子栏目,使用匹配结尾的语法,可以防止提取到这些子栏目的 URL。
16.1.2 知乎网站进一步分析
从上面的分析已经知道了链接提取的规则,但是还有一个问题应该注意,那就是知乎网页是动态网页。前面已经注意到,要查看用户个人详细资料,需要单击“查看详细资料”,这就是动态网站的明显特征 - URL 不变但加载了新的数据。不仅如此,知乎网站为了让用户更快打开页面、减轻服务器压力,整个网站都存着这种异步加载的情况。例如,打开某个用户的关注对象列表页面,如图 16-3 所示。
图 16-3 用户的关注对象列表页面
实际页面上直接加载的只有前 3 个关注对象,其他的关注对象信息都是异步加载进来的。为了验证这一点,可以在页面空白处单击右键,查看源码,这时就会发现上、下两部分源码的形式完全不同。在 scrapy shell 中直接使用 scrapy.Request,请求某一个用户的关注对象列表页面,查看返回的 response.body,也能发现这一点。
要解决这个问题,按照以前讲的思路,既可以使用 Selenium 配合 Chrome 浏览器加载动态网页,也可以仔细分析网页的请求和返回数据情况,找到加载这些 json 数据的请求,然后构造这个请求,获取返回数据。在 Scrapy 框架中,可以使用 Selenium 配合 Chrome 浏览器解析动态网页,一般我们都是通过修改下载中间件,改变 Scrapy 请求网络的方式,让其使用 Selenium 和 Chrome 浏览器来完成下载网页的动作,并将收到的响应返回,但是这种处理方式的爬取效率比较低,并且从收到的响应中解析出我们需要的内容也比较麻烦;分析网页实际请求的这种解决办法效率非常高,但需要仔细分析请求过程,构造实际请求的网址,分析起来比较麻烦,若有兴趣,读者可以自己尝试一下。在这里为了简单,只爬取每个用户关注对象列表页面和粉丝列表页面中直接显示的那前 3 个人的信息,然后利用关注和被关注关系,一直循环下去,直到抓取全部数据。
另外,我们在加载用户个人页面时,有时候会发现某些人的个人页面在不登录的情况下是显示不出来的,如果要抓取这些人的详细信息,需要处理 Scrapy 登录等很多情况,这里直接忽略这些用户即可。其实从抓取的目标来看,我们希望抓取的是那些粉丝众多的“大 V”,既然部分用户并不希望传播和曝光,直接放弃抓取这些人的资料就可以了。
通过本节的分析,我们对知乎网站已经有了一定的了解,下一节就用代码实现抓取知乎用户的数据。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论