Python实现网络爬虫基础学习(四)

抓取评论数的方法------函数

将方法写成一个函数式,这样每次就只需要改变链接就可以获取我们要得到的总评论数 

而且我们每次只要更新新闻的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))#打印出抓取到的新闻信息

猜你喜欢

转载自blog.csdn.net/weixin_42280639/article/details/81208214