抓取评论数的方法------函数
将方法写成一个函数式,这样每次就只需要改变链接就可以获取我们要得到的总评论数
而且我们每次只要更新新闻的id即可,所以将我们获取的链接中的id去除掉,用一个{}代替,每次改变了连接后,我们只需要将id写入前一个链接即可。newsid=comos-hftenhz3270493&变为newsid=comos-{}&
下面开始进行操作
import requests
# 先给出一个统一的URL链接格式
url = "http://comment5.news.sina.com.cn/page/info?version=1&format=json&channel=gn&newsid=comos-{}&group=undefined&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=3&t_size=3&h_size=3&thread=1"
import re # 导入re套件
import json
#获取新闻评论数
def getUrlCounts(newsurl):
m = re.search("doc-i(.+).shtml", newsurl) # 获取新闻id
newsid = m.group(1) # 只要id部分
com = requests.get(url.format(newsid)) # 将刚获取到的id嵌套进统一的URL当中
count = json.loads(com.text.strip("jsonp_1532503523980")) # 获取含有评论数的整条数据
# 从获取到的数据当中筛选出评论总数,位于字典result下的,count下的total中
return count['result']['count']['total']
# 随意选取一个链接,此处的链接就是可以每次进行更改,
news = "http://news.sina.com.cn/c/gat/2018-07-23/doc-ihftenhz1878392.shtml"
c = getUrlCounts(news)#调用getUrlCounts和函数,获取我们要的评论总数
print(c)
新闻内文信息抽取------函数
抓取内文的标题、新闻来源、时间、责任编辑、内文内容,将获取到的内容存放进一个字典当中
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import re # 导入re套件
import json
# 先给出一个统一的URL链接格式
url = "http://comment5.news.sina.com.cn/page/info?version=1&format=json&channel=gn&newsid=comos-{}&group=undefined&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=3&t_size=3&h_size=3&thread=1"
# 将要获取的链接,此处的链接就是可以每次进行更改,
newsurl = "http://news.sina.com.cn/c/gat/2018-07-23/doc-ihftenhz1878392.shtml"
# 获取新闻评论数
def getCommentCounts(newsurl):
m = re.search("doc-i(.+).shtml", newsurl) # 获取新闻id
newsid = m.group(1) # 只要id部分
com = requests.get(url.format(newsid)) # 将刚获取到的id嵌套进统一的URL当中
count = json.loads(com.text.strip("jsonp_1532503523980")) # 获取含有评论数的整条数据
# 从获取到的数据当中筛选出评论总数,位于字典result下的,count下的total中
return count['result']['count']['total']
def getNewsDetail(newsurl):
result = {} # 定义一个存放数据的字典
res = requests.get(newsurl)
res.encoding = "utf-8"
soup = BeautifulSoup(res.text, "html.parser")
result['title'] = soup.select(
'body > div.main-content.w1240 > h1')[0].text # 文章标题
result['newssource'] = soup.select('.date-source a')[0].text # 新闻来源
result['datetime'] = soup.select(
'.date-source')[0].text.strip().rstrip('\n参考消息网')
result['article'] = ' '.join([p.text.strip()
for p in soup.select(".article p")[:-1]]) # 内文
result['editor'] = soup.select(".show_author")[
0].text.lstrip('责任编辑:') # 责任编辑
result['comments'] = getCommentCounts(
newsurl) # 调用getUrlCounts和函数,获取我们要的评论总数
return result
print(getNewsDetail(newsurl))
从列表连结取出每篇新闻内容
我们已经可以截取一篇新闻的内容等信息,那么我们可以开始获取列表内的信息
(非同步载入)
点击header,复制对应的链接
这里有分页12345,根据刚刚复制的链接,我们还可以点击第2 页,再看一下他的链接与第一页的链接有什么不同,从而找出他的分页的规律
可以看见另一页的内容,那么我们对比比一下两个页面的链接有什么区别
http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gnxw&cat_2==gdxw1||=gatxw||=zs-pl||=mtjj&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page=1&callback=newsloadercallback&_=1532525179943
http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gnxw&cat_2==gdxw1||=gatxw||=zs-pl||=mtjj&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page=4&callback=newsloadercallback&_=1532524859175
对比之后发现,两者除了page处其余几乎没有区别
因此,我们只要改变page后的值就可以将所有页面的新闻的内容全部抓取,先试试第一个页面
# 获取新闻列表信息
res2 = requests.get(
"http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gnxw&cat_2==gdxw1||=gatxw||=zs-pl||=mtjj&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page=1")
r = res2.text.lstrip("newsloadercallback(").rstrip(");")
j = json.loads(r)
j1 = j['result']['data']
for i in j1:
print(i['title'], i['url'])
那么我们试试抓取连结列表的信息,建立一个函数 ,之后每次只要给一个不同的api链接,就可以抓取这些链接下的数据,再套用之前所做的内容就可以摘取出这些链接对应的内文。
在之前的代码基础上,添加 即可
# 获取新闻列表连结的新闻信息
def getListLinks(urllist):
newsdetails = []
res2 = requests.get(urllist)#获取新闻列表数据
r = res2.text.lstrip("newsloadercallback(").rstrip(");")
j = json.loads(r)
j1 = j['result']['data']
for i in j1:
newsdetails.append(getNewsDetail(i['url']))#获取链接url对应的内文数据
return newsdetails
a = getListLinks(urllist)
for i in range(len(a)):#由于得到的是一个list,所以采用循环的方式将list内的每一条新闻内容逐行打印,方便查看
print(a[i])
如此就可以获得一个页面的信息
使用for循环产生多页连结
刚才我们已经了解到这些网页链接列表的链接URL中,链接几乎相同,只是page处会有变化,那么我们就可以像上面获取id一样,把id嵌套进连接中,此时我们也可以这样操作,将page后的数字改为page={},通过循环就可以实现。下面开始具体操作:可以看见下图中页面共有5页,那么我们的循环可以写成for i in range(1,6):表示i=1;i<6;i++
这样我们就已经获取了这些页面的链接,再调用之前的函数就可以获得这些页面的具体数据 ,由于如果打印的页面过多时,耗时会比较长,所以我采用了只打印两个连结页面的数据,也就是一共44条数据
# 新闻列表含有多个页面时,只需更改page即可
urllist = "http://api.roll.news.sina.com.cn/zt_list?channel=news&cat_1=gnxw&cat_2==gdxw1||=gatxw||=zs-pl||=mtjj&level==1||=2&show_ext=1&show_all=1&show_num=22&tag=1&format=json&page={}"
# 每次更改连结页面页数即可
news_total = []
for i in range(1, 3):#新闻页数
urllist1 = urllist.format(i) # 将i放在链接上
news = getListLinks(urllist1) # 获取新闻内容
news_total.extend(news) # 将抓取的资料放入list中
# 由于得到的是一个list,所以采用循环的方式将list内的每一条新闻内容逐行打印,方便查看
for j in range(len(news_total)):
print(news_total[j])
print("共抓取到 %d条新闻" % len(news_total))#打印出抓取到的新闻信息