数据采集:采集Ajax动态网站,抓取娱乐热点新闻标题并作简要分析

八卦是人的天性,我作为众多吃瓜群众中的一员,当然也不会放过娱乐圈中的每一个热点。
接下来我会抓取企鹅网的娱乐版块 https://new.qq.com/ch/ent/
看看各位娱乐小编是如何报道娱乐热点的。
具体目标如下图:(红色方框内的标题)
在这里插入图片描述

  1. 第一步就是“观察与分析”,不断下拉滚动条,右键点击查看源代码,右键点击检查,这些都是基本操作了,可以发现网站是Ajax加载,返回的数据都在Json里,如下图:
    在这里插入图片描述
  2. 接下来就可以进行基本的抓取,代码如下(文件名为news_of_ent_v1.py):
import requests
import json
import uagent #我自己编写的一个获取随机user-agent的脚本,可参考https://blog.csdn.net/eighttoes/article/details/82996377

url = ('https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e5372337'
	   '2ce&ext=ent&page=3&expIds=20181129V094JT|20181129A09LA4|20181129A09DI3|h08046y2'
	   '39w|20181129A0AEFT|20181129A09L7P|20181129A0A0A3|w0804cm6v49|20181129A07WGU|201'
	   '81129V07R1F|20181129A07YTG|i0804um2sgw|20181129A03RFA|20181129V08K9U|20181129A0'
	   '752A|r0804pauuow|20181129A03M8L|20181129V05VUW|20181129A07RY8|i0804rrvezl&callb'
	   'ack=__jp9')

def get_page(url):
	headers = {'User-Agent': uagent.get_ua()}
	response = requests.get(url = url, headers = headers)
	index = response.text.index('{')
	text = response.text[index:-1] #因为返回的字符串不符合Json格式,所有需要截取
	return text

def parse(text):
	dic = json.loads(text)
	for i in dic['data']:
		title = i['title']
		print(title)

if __name__ == '__main__':
	text = get_page(url)
	parse(text)

在这里插入图片描述

  1. 第三步可以开始考虑如何进行多页的数据抓取,一般来说可以观察多个url之间的规律,

https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=5&expIds=20181129A0431M|20181129A0GCCJ|20181129A0CWFL|m0804l0n718|20181129A0DXZT|20181128A041V1|20181129A0BAHH|l0804e3dmbo|20181129A0F6R9|20181129A0EESO|20181127A154YM|l0804qtam7g|20181129A0ETEU|20181129A0H1J0|20181129V0EZAD|i0804iftf8b|20181129A0HEU1|20181129A0HEA6&callback=__jp11

https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=6&expIds=20181129A0HDOG|20181129A0H8CM|20181129A0H6ZO|l0804e3dmbo|20181129A0H6JU|20181129A0H1D0|20181129A0H0VJ|o0804dfc16w|20181129A0GU2A|20181129A0GPHC|20181129A0GJF9|w08042hmn7v|20181129A0GEM6|20181129A0GCE0|20181129A0GAW5|p08042xdhx2|20181129A0G09R|20181129A0FZKK&callback=__jp12

https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=7&expIds=20181129A0FM76|20181129A0FAHO|20181129A0F9F9|u080493vmrd|20181129A0F8SG|20181129A0F8KW|20181129A0DQ1O|g0804wb0r2h|20181129A0DIMJ|20181129A0DFVG|20181129A044D0|z080490ojod|20181127V1HHOY|20181129A0CZBG|20181129A0B8NS|i0804ilfina|20181129A0D98X|20181129A0AOPL|20181129V05VUW&callback=__jp13

url参数有变化的分别是page,expIds,callback。
page和callback都很好理解,就是一个递增的数字,至于expIds,这么一大串的东西是什么呢,我从刚刚抓取的Json数据里找到了线索,其中id字段就组成下一页url的关键信息。
在这里插入图片描述
在这里插入图片描述
那么接下来就可以开始编辑代码了,如下所示(文件名为news_of_ent_v2.py):

import requests
import json
import uagent #我自己编写的一个获取随机user-agent的脚本,可参考https://blog.csdn.net/eighttoes/article/details/82996377

def get_page(n, expIds): #page从1开始,callback = page + 6
	base_url = 'https://pacaio.match.qq.com/irs/rcd'
	payload = {
		'cid': '146',
		'token': '49cbb2154853ef1a74ff4e53723372ce',
		'ext': 'ent',
		'page': str(n),
		'expIds': expIds,
		'callback': '__jp' + str(n + 6)
	}
	headers = {'User-Agent': uagent.get_ua()}
	response = requests.get(url = base_url, params = payload, headers = headers)
	index = response.text.index('{')
	text = response.text[index:-1] #因为返回的字符串不符合Json格式,所有需要截取
	return text

def parse_title(text):
	dic = json.loads(text)
	for i in dic['data']:
		title = i['title']
		print(title)

def parse_id(text):
	dic = json.loads(text)
	expIds = ''
	for i in dic['data']:
		expIds += i['id']
		expIds += '|'
	return expIds[:-1]



if __name__ == '__main__':
	expIds = ('20181129001615|20181129A0JFDT|20181128A0Z1JV|l0804gy5rsa|20181129A0K'
		      'LSB|20181129A0D0LP|20181129A02B6B|n0804d5mx3y|20181128A1K7IZ|20181129'
		      'A09LA4|20181129A060VB|s0804loccct|20181129A0KIZU|20181129A0AEFT|20181'
		      '129A0PGAG|w0804wyseww|20181129009640|20181129A0JLZQ|20181129A06G5R')
	for n in range(1, 11):
		text = get_page(n, expIds)
		parse_title(text)
		expIds = parse_id(text)
修改了get_page()函数,添加了构造url的逻辑,而不是直接把url当作参数传入,然后添加了一个解析expIds的函数。
  1. 第四步就要开始考虑保存数据了,因为数据量不大,而且只有1个字段,直接保存为一个csv文件就可以了。
    代码如下(文件名为news_of_ent_v3.py):
import requests
import json
import uagent #我自己编写的一个获取随机user-agent的脚本,可参考https://blog.csdn.net/eighttoes/article/details/82996377
import csv

def get_page(n, expIds): #page从1开始,callback = page + 6
	base_url = 'https://pacaio.match.qq.com/irs/rcd'
	payload = {
		'cid': '146',
		'token': '49cbb2154853ef1a74ff4e53723372ce',
		'ext': 'ent',
		'page': str(n),
		'expIds': expIds,
		'callback': '__jp' + str(n + 6)
	}
	headers = {'User-Agent': uagent.get_ua()}
	response = requests.get(url = base_url, params = payload, headers = headers)
	index = response.text.index('{')
	text = response.text[index:-1] #因为返回的字符串不符合Json格式,所有需要截取
	return text

def parse_title(text):
	dic = json.loads(text)
	titles = [i['title'] for i in dic['data']]
	return titles

def parse_id(text):
	dic = json.loads(text)
	expIds = ''
	for i in dic['data']:
		expIds += i['id']
		expIds += '|'
	return expIds[:-1]

def save(data):
	#encoding用一个比较大的汉字字符集,防止出现不能识别的汉字
	with open('titles.csv', 'a', newline = '', encoding = 'GB18030') as c:
		writer = csv.writer(c)
		for i in data:
			writer.writerow([i])



if __name__ == '__main__':
	#这里对第一个expIds进行硬编码
	expIds = ('20181129001615|20181129A0JFDT|20181128A0Z1JV|l0804gy5rsa|20181129A0K'
		      'LSB|20181129A0D0LP|20181129A02B6B|n0804d5mx3y|20181128A1K7IZ|20181129'
		      'A09LA4|20181129A060VB|s0804loccct|20181129A0KIZU|20181129A0AEFT|20181'
		      '129A0PGAG|w0804wyseww|20181129009640|20181129A0JLZQ|20181129A06G5R')
	for n in range(1, 11):
		text = get_page(n, expIds)
		data = parse_title(text)
		save(data)
		print('the', n, 'page ok')
		expIds = parse_id(text)
将parse_title()函数改为返回一个列表推导式,并新增了一个save()函数。

####我一开始打算抓取1万页的数据,不过到了约20页左右,每页的标题数量就从20个下降到4-5个,我一开始以为是遇到什么反爬策略了,于是用浏览器加载看看,发现也是一样。
然后用脚本抓取到大概2000多页的时候,直接就没有标题返回了,我想应该是企鹅网直接把旧的过期缓存删掉吧,正常人也不会看一个版的新闻,下拉到2000多页。。。
这里我挖掘了3235个标题,下面进行一下简要的分析。
在这里插入图片描述
首先我发现,作为一名专业的小编,在起标题的时候,是绝对不能使用句号的,但是可以使用问号?和感叹号!
而且不能使用简单的几个词语来起标题,标题一般都比较长,需要用逗号来拼接。
在这里插入图片描述
至于标题的字数一般控制在20-32个左右,只有极少数会出现在10个字以下,或者35个字以上。
在这里插入图片描述
由于标题必须和内容具有相关性,相信只要具有初中语文水平的同学都会知道这个道理。
虽然近年来,出现了非常非常多的标题党,但是对于标题中的主角一般不会假,因此接下来可以通过标题来看看这两天(我这篇博客写于18年11月29日)热度最高的10位艺人分别是谁?
在这里插入图片描述
可以看出基本和昨天(18年11月28日)的娱乐新闻八九不离十,除了赵丽颖,我不知道发生了什么。。。

总结

通过分析Ajax,仅仅利用requests和json库就可以进行数据的挖掘,保存数据利用了csv库。
至于后期的数据可视化,分别使用了pandas读取并操作csv,jieba进行分词,collections中的Counter进行词频统计,plt画图。

猜你喜欢

转载自blog.csdn.net/eighttoes/article/details/84621066