Dust8 的博客

读书百遍其义自见

0%

网易新闻评论爬虫

前言

昨天有 _ boss _ 给我出了一道爬虫题,让我爬网易新闻的评论,我说试下。

分析

一级入口

网易新闻的入口:_ news.163.com _

二级人口:


点击进去查看源代码,发现没有内容,可以知道它是 动态加载 的。
通过 _ Network _ 里面的 _ XHR _,并没有发现请求,查看 JS
发现一个可疑请求

就是它了 http://temp.163.com/special/00804KVA/cm_guonei.js?callback=data_callback
通过它就可以得到 guonei 的最近新闻内容)。

注意这里 cm_guonei 和开始进来的 domestic ,它们名字并不统一

评论入口

同理可以发现

  • 最热评论 hotList
  • 最新评论 newList

注意每个二级的评论接口有可能不一样。比如国内新闻的评论接口是 http://comment.news.163.com
而军事评论接口是 http://comment.war.163.com

代码

用 _ scrapy _ 来写也很简单,平常那种连续 2 次解析就可以了。

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
40
41
42
43
44
45
46
47
48
49
import re
import json
import scrapy

from ..items import NewsItem, CommentItem


class NewsSpider(scrapy.Spider):
name = 'news'
CM_API_BASE_URL = 'http://temp.163.com/special/00804KVA/cm_{}.js?callback=data_callback'
NEW_LIST_API_BASE_URL = 'http://comment.news.163.com/api/v1/products/a2869674571f77b5a0867c3d71db5856/threads/{}/comments/newList?offset=0&limit=30&showLevelThreshold=72&headLimit=1&tailLimit=2&callback=getData&ibc=newspc'
pingdao = ['shehui', 'guoji','war']
start_urls = [CM_API_BASE_URL.format('guonei')]

def parse(self, response):
cm_re = re.compile('data_callback\((.*)\)', re.DOTALL)
m = cm_re.match(response.body.decode('gb18030'))
if m:
newses = json.loads(m.group(1))
for news in newses:
item = NewsItem()
item['channelname'] = news['channelname']
item['docurl'] = news['docurl']
item['time'] = news['time']
item['title'] = news['title']
item['threadid'] = news['docurl'][-21:-5]
yield item

request = scrapy.Request(self.NEW_LIST_API_BASE_URL.format(item['threadid']),
callback=self.parse_comment)
request.meta['threadid'] = item['threadid']
yield request

def parse_comment(self, response):
threadid = response.meta['threadid']
new_list_re = re.compile('getData\((.*)\)', re.DOTALL)
m = new_list_re.match(response.body.decode())
if m:
comments = json.loads(m.group(1))['comments']
for _, value in comments.items():
# print(value)
item = CommentItem()
item['commentid'] = value['commentId']
item['content'] = value['content']
item['createtime'] = value['createTime']
item['threadid'] = threadid
item['nickname'] = value['user'].get('nickname', 'anonymous')
item['userid'] = value['user'].get('userId', '0')
yield item

抓取结果

只抓取了一次国内新闻。共 _ 70 _ 条新闻,_ 2012 _ 条评论。

需要改进的

  • 因为抓取的都是最近新闻,可能没有多少评论,需要以后再次抓取评论来提高评论的数量
  • 过去的新闻没有去抓