分析一个爬虫的分页问题

接着这篇《Python爬取数据的分页分析》,最后的难点地方:滚动分页,不知道总页数的情况,如何确定爬虫的分页抓取。
以的“个人主页”-- “动态”为例来说明。
分析一个爬虫的分页问题
文章图片
先看一下“个人动态”中有哪些数据:评论,喜欢,打赏,关注(作者、专题)(这些都指的是对他人的文章),发表文章(自己),还有一个重要数据“加入”(注册时间)。

## 用户行为类型 ## share_note 发表文章 ## like_collection 关注专题 ## comment_note 发表评论 ## like_comment 赞了评论 ## reward_note 打赏文章 ## like_user 关注作者

再看一下网页结构,在个人主页下 看动态,是一个tab切换,有 文章 -- 动态 -- 最新评论 -- 热门,默认情况下,看到的是“文章”这个tab,切换到“动态”tab下,就可以看到用户在上一系列的行为操作和时间。不断下拉滚动条,看到所有记录,最后一条是用户的注册时间。
一个典型的滚动分页,不知道总页数。那爬虫如何确定分页的URL,抓取到所有数据呢?
特别注意,因为这个页面采用的框架页,进到用户主页,切换到“动态”tab,查看源代码,是看不到“动态”内容的源代码的。这个也给我们确定分页的URL中的参数造成难题。
还是用Chrome -- 检查 -- Network 工具来分析一下 第2页,第3页的URL,找找规律:
这是第2页URL:
http://www.jianshu.com/users/1441f4ae075d/timeline?max_id=97250697&page=2

【分析一个爬虫的分页问题】第3页URL:
http://www.jianshu.com/users/1441f4ae075d/timeline?max_id=94439065&page=3

基本可以确定,分页URL是userid/timeline?max_id=xxx&page=x,URL中需要这样两个参数:max_id和page,max_id是什么鬼,这个就是这里分页的最关键的地方,还有一共有多少页怎么确定,也就是爬虫需要递归调用多少次才结束。
还有一点,需要同时看一下,第2页、第3页分页返回的是xml数据(一段网页代码),也就是这时最大程度复用了页面,用的Ajax。
第一步,先确定max_id,还是要到页面源代码中找蛛丝马迹,如果按照一开始进到用户主页,切到“动态”tab,别说max_id找不到,就连页面的那些内容也找不到。陷入僵局的状态。这个max_id看名字就不像时间戳,而像是页面开始的数据id。
关键原因是框架页面挡住了我们的视线,把第2页、第3页的URL直接粘到地址栏回车,查看源代码,一切都有了。
分析一个爬虫的分页问题
文章图片
把刚刚分页URL中的那个max_id搜一下,有木有。我的猜想是最后一个id。顺着这个思路往下就比较好弄了。关键是拿出

  • 当中的id去构造一个分页URL就行了,然后顺序往下翻,直到最后一页为止。
    不细说了,如何确定max_id,如何提取max_id,如何确定最后一页。
    好啦,我直接上源码:
    #coding=utf-8 import requests from lxml import etree## 抓取用户timeline数据 headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36' }def get_info(url,page):uid= url.split('/') uid= uid[4]if url.find('page='): page = page+1html = requests.get(url,headers=headers).content selector = etree.HTML(html)infos2 = selector.xpath('//ul[@class="note-list"]/li/@id')infos = selector.xpath('//ul[@class="note-list"]/li') for info in infos: name = info.xpath('div/div/div/a/text()')[0] dd = info.xpath('div/div/div/span/@data-datetime')[0] type = info.xpath('div/div/div/span/@data-type')[0] print type print ddif len(infos) > 1: tid = infos2[len(infos2) - 1] tid = int(filter(str.isdigit, tid)) - 1 print tidnext_url = 'http://www.jianshu.com/users/%s/timeline?max_id=%s&page=%s' % (uid, tid, page)get_info(next_url,page)get_info('http://www.jianshu.com/users/54b5900965ea/timeline',1)

    Github: https://github.com/ppy2790/author/, 可以比较一下Scrapy 和直接用 requests 两种方式的代码有什么不同。
    经验:大胆设想,小心求证,简化处理,认真查找,反复折腾。

      推荐阅读