网络爬虫——用Python爬取新浪新闻材料

微信公众号:数据分析与统计学习
如有问题或建议,请公众号留言
最近更新时间:2018-7-8

最近一个星期都在学习网络爬虫,秉着有学习输入就要有学习输出(学以致用)的原则,把整个学习过程记录下来,并分享给大家。

一、 爬虫前的准备工作

我是在Windows系统下用Python的Anaconda集成开发环境实现网络爬取新浪新闻项目。用Anaconda实现网络爬虫有如下几个好处:第一,该软件是免费的;第二,该集成开发环境已经具备网络爬虫所需的库,不需要我们安装第三方库。
下载谷歌浏览器的一个第三方插件SelectorGadget,主要是用来辅助定位网页元素的位置以及查找出各网页元素的共同规律。具体用法可以上网搜索。

二、 网络爬虫流程说明

一个轻量级的网络爬虫项目,应该具备如下两个步骤。第一,获取网页上的目标链接(URL);第二,目标网页解析,从网页中提取我们所需要的数据。

三、 网络爬虫代码实现

在敲击键盘编写代码实现爬虫项目的过程中,主要用到Python中三个第三方库——requests 、BeautifulSoup和json以及用于存储数据的pandas库。
requests库主要用途获取目标网页的内容,爬虫过程中主要用到它的get方法,接受参数URL,就返回一个包含目标内容的Response对象。详细用法请参考requests库的中文文档。链接如下:
http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

BeautifulSoup库主要用途是解析目标网页内容,接受一个网页内容的参数,返回一个BeautifulSoup对象。主要用到该库的find_all,find,select等方法。详细用法请参考BeautifulSoup库的中文文档。链接如下:
https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/

json库主要用来从网页中提取json格式的数据。json格式数据转换后,变成Python的字典。

1、今天我要爬取的网页是新浪新闻国内新闻的最新消息一栏,先打开新浪新闻国内新闻网页,如下图所示:

网络爬虫——用Python爬取新浪新闻材料_第1张图片
新浪新闻.png

2、然后在网页空白地方点击右键,选择“检查”,然后选择‘element’选项卡,利用谷歌浏览器插件SelectorGadget,点击各新闻标题,寻找各新闻标题元素的位置。找到各新闻标题元素的位置后,寻找共同规律。我发现这些新闻标题的位置均在属性class=“newsitem”,并且这些新闻标题的链接都存储在标签中href属性。具体代码如下:

import requestsfrom bs4 import BeautifulSoup
def urls_download(url):     #定义下载这些新闻标题链接的函数    
    r = requests.get(url)   #传入参数,获取参数所代表的网页    
    r.encoding = 'utf-8'    #显性设定编码为utf-8    
    bsobj = BeautifulSoup(r.text,'lxml') #接收目标网页内容,解析网页   
    alinks = bsobj.select('.news-item')  #返还含有新闻标题元素的列表    
    newsurls = []  #收集新闻标题的链接    
    for alink in alinks:            
           hrefs = alink.select('a')            
           if  hrefs:     #排除新闻标题链接为空的情况             
                newsurls.append(hrefs[0]['href'])
return newsurls  #返回目标网页链接列表

3、获取目标网页链接列表后,对每个链接的网页进行解析,从中提取目标新闻网页的的数据,包括标题、时间、来源、编辑者、文章内容,评论数、关键词。具体实现代码如下;

import json
import requests
from bs4 import BeautifulSoup
def getNewsDetails(url):
    r = requests.get(url)    r.encoding = 'utf-8'
    bsobj = BeautifulSoup(r.text,'lxml')
    result = {}  #收集目标网页的数据
    result['main_title'] = bsobj.select('.main-title')[0].text 
    result['date'] = bsobj.select('.date')[0].text
    try:   #异常处理,处理标签\中href属性不存在的情况 
       result['source'] = bsobj.select('.source')[0].text
        result['source_link'] = bsobj.select('.source')[0]['href']
    except  KeyError: 
          print("has no key")
    result['show_author'] = bsobj.select('.show_author')[0].text.lstrip('责任编辑:')
    result['keywords'] = bsobj.select('.keywords')[0]['data-wbkey'][:-3]
    texts = [] #收集新闻的具体内容
    for i in range(len(bsobj.select('p'))-5):
        texts.append(bsobj.select('p')[i].text.replace(u'\u3000',u'')) #去除每段的首行两个空白字符
             result['article'] = texts
     news_id = url.split('/')[-1].rstrip('.shtml').lstrip('doc-i')
     commenturl = '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'
     comments = requests.get(commenturl.format(news_id)) #评论数是json格式的数据
     comment = comments.text
     jd = json.loads(comment) #转换json格式的数据 
     result['comment_num'] = jd['result']['count']['total'] 
     return result #返回所需的数据

上面只是一个网页的,因为一个新闻网页肯定有许多页,需要翻页看,如果想获取不同分页下的网页链接,就要重新编写代码,具体代码:

def parseListLinks(url): #定义获取不同分页下的新闻标题链接函数
    newsDetail= []
    r = requests.get(url) 
   jsondata = r.text.strip().lstrip('newsloadercallback(').rstrip(');') 
   jd = json.loads(jsondata) 
   for i in range(len(jd['result']['data'])): 
       newsDetail.append(getNewsDetails(jd['result']['data'][i]['url']))  #调用前面获取新闻数据的函数,获取每个分页下所有新闻的数据 
   return newsDetail 返回所有分页下的新闻数据
#不同分页的URL链接url = '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={}&callback=newsloadercallback&_=1531402221318' 
news_total = [] #手机所有新闻数据的列表for i in range(1,5): 
   news_list = parseListLinks(url.format(i))
    news_total.extend(news_list)  #把爬取的数据下载下来,把数据存储到csv
import pandas as pd
df = pd.DataFrame(news_total) #列表转换为数据框
df.to_csv('news.csv') #存储到名为news格式为csv的表中

四、后记

这只是一个简单的网络爬虫,后面还有更多的内容需要学习,我也会把自己学到的最新的网络爬虫知识分享给大家。希望大家继续保持关注,也希望大家积极留言指出我的错误,教学相长。


下面的是我的公众号二维码图片,欢迎关注我。

你可能感兴趣的:(网络爬虫——用Python爬取新浪新闻材料)