Python爬虫:抓取新浪新闻数据
案例一
抓取对象:
新浪国内新闻(http://news.sina.com.cn/china/),该列表中的标题名称、时间、链接。

完整代码:
from bs4 import BeautifulSoup
import requests
url = 'http://news.sina.com.cn/china/'
web_data = requests.get(url)
web_data.encoding = 'utf-8'
soup = BeautifulSoup(web_data.text,'lxml')
for news in soup.select('.news-item'):
if(len(news.select('h2')) > 0):
h2 = news.select('h2')[0].text
time = news.select('.time')[0].text
a = news.select('a')[0]['href']
print(h2,time,a)
运行结果:(只展示部分)

详细解说:
1. 首先插入需要用到的库:BeautifulSoup、requests,然后解析网页。解析完后print下,确认是否解析正确。
from bs4 import BeautifulSoup import requests url = 'http://news.sina.com.cn/china/' web_data = requests.get(url) soup = BeautifulSoup(web_data.text,'lxml') print(soup)
这时,我们可以看到,解析出来的网页里面有很多乱码,并没有正确解析。观察下结果,看到开头的这句:
<meta content="text/html; charset=utf-8" http-equiv="Content-type"/>
【charset=utf-8】表示当前内容的字符集是采用utf-8编码格式,所以我们需要用encoding来解锁下,这时就能解析出来正常内容。
from bs4 import BeautifulSoup import requests url = 'http://news.sina.com.cn/china/' web_data = requests.get(url) web_data.encoding = 'utf-8' soup = BeautifulSoup(web_data.text,'lxml') print(soup)
2. 解析出网页后,开始抓取我们需要的内容。首先,先补充几点知识。
看下面代码中的第一行,soup.select('.news-item'),取出含有特定CSS属性的元素时,比如:
- 找出所有class为news-item的元素,class名前面需要加点(.),即英文状态下的句号;
- 找出所有id为artibodyTitle的元素,id名前面需要加井号(#)。
另外,取得含有特定标签的HTML元素时,直接在select后写标签名即可,如下面for循环中的第3行,news.select('h2')。
for news in soup.select('.news-item'):
# print(news)
if(len(news.select('h2')) > 0):
# print(news.select('h2')[0].text)
h2 = news.select('h2')[0].text
time = news.select('.time')[0].text
a = news.select('a')[0]['href']
print(h2,time,a)
现在来详细看下这段代码每行的释义。
第1行:soup.select('.news-item'),取出news-item该类中的元素;
第2行:print下news,查看是否被正常解析,正常后继续,不用时可以注释掉;
第3行:通过观察代码,可以看到标题被储存在标签h2中,如果h2的长度大于0,这里是为了去除为空的标题数据;
第4行:print中news.select('h2')[0].text,[0]是取该列表中的第一个元素,text是取文本数据,print后查看是否正确,不用时可以注释掉;
第5行:将news.select('h2')[0].text存储在变量h2中;
第6行:time是class类型,前面加点来表示,同上,将其数据存储在变量time中;
第7行:我们要抓取的链接存放在a标签中,链接已经不是text了,后面用href,将链接数据存储在变量a中;
第8行:最后输出我们想要抓取的数据,标题、时间、链接。
案例二
抓取对象:
抓取新闻详情页的标题、时间(进行格式转换)、新闻来源、新闻详情、责任编辑、评论数量和新闻ID。
示例新闻:http://news.sina.com.cn/c/nd/2017-05-08/doc-ifyeycfp9368908.shtml
完整代码:
from bs4 import BeautifulSoup
import requests
from datetime import datetime
import json
import re
news_url = 'http://news.sina.com.cn/c/nd/2017-05-08/doc-ifyeycfp9368908.shtml'
web_data = requests.get(news_url)
web_data.encoding = 'utf-8'
soup = BeautifulSoup(web_data.text,'lxml')
title = soup.select('#artibodyTitle')[0].text
print(title)
time = soup.select('.time-source')[0].contents[0].strip()
dt = datetime.strptime(time,'%Y年%m月%d日%H:%M')
print(dt)
source = soup.select('.time-source span span a')[0].text
print(source)
print('\n'.join([p.text.strip() for p in soup.select('#artibody p')[:-1]]))
editor = soup.select('.article-editor')[0].text.lstrip('责任编辑:')
print(editor)
comments = requests.get('http://comment5.news.sina.com.cn/page/info?version=1&format=js&channel=gn&newsid=comos-fyeycfp9368908&group=&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=20')
comments_total = json.loads(comments.text.strip('var data='))
print(comments_total['result']['count']['total'])
news_id = re.search('doc-i(.+).shtml',news_url)
print(news_id.group(1))
fyeycfp9368908
详细解说:
1. 首先插入需要用到的库:BeautifulSoup、requests、datetime(时间处理)、json(解码:把json格式字符串解码转换成Python对象)、re(正则表达式),然后解析网页。
先抓取标题:
from bs4 import BeautifulSoup
import requests
from datetime import datetime
import json
import re
url = 'http://news.sina.com.cn/c/nd/2017-05-08/doc-ifyeycfp9368908.shtml'
web_data = requests.get(url)
web_data.encoding = 'utf-8'
soup = BeautifulSoup(web_data.text,'lxml')
title = soup.select('#artibodyTitle')[0].text
print(title)
datetime、json、re在后面时间转换和从js中抓取数据时会用到。
我们主要来看下倒数第二行代码:title = soup.select('#artibodyTitle')[0].text,这里的用法和案例一中一样,id前用井号(#)来表示该类元素的位置,解锁唯一元素用[0],提取文本信息text。
2. 抓取时间,并将原有日期格式转化为标准格式:
# time = soup.select('.time-source')[0]
# print(time)
time = soup.select('.time-source')[0].contents[0].strip()
dt = datetime.strptime(time,'%Y年%m月%d日%H:%M')
print(dt)
第1行:抓取时间;
第2行:print下时间,这时会发现运行结果中既含有时间,还有新闻的来源,如下:
<span class="time-source" id="navtimeSource">2017年05月08日17:21 <span> <span data-sudaclick="media_name"><a href="http://m.news.cctv.com/2017/05/08/ARTIPEcvpHjWzuGDPWQhn77z170508.shtml" rel="nofollow" target="_blank">央视新闻</a></span></span> </span>
那么,接下来我们需要想办法将时间和来源分开来,这时需要使用到contents;
第3行:我们先在后面加上.contents,运行下后会看到上面的内容会在列表中分为如下2个元素,此时,我们取的时间为第一个元素,在contents后加[0],最后的.strip()可以去除时间末尾的\t;
['2017年05月08日17:21\t\t', <span> <span data-sudaclick="media_name"><a href="http://m.news.cctv.com/2017/05/08/ARTIPEcvpHjWzuGDPWQhn77z170508.shtml" rel="nofollow" target="_blank">央视新闻</a></span></span>, '\n']
第4行:用datetime.strptime()来做时间格式化,原有的时间是年月日时分,所以转化时用到年月日时分,其中%Y是四位数的年份表示、%m是月份、%d是月份内的一天、%H是24小时制中的小时、%M是分钟数,并将其存储在变量dt中;
第5行:输出dt,会得到格式化后的时间,比如:2017-05-08 17:21:00。
3. 抓取新闻来源:
之前文章《Python爬虫:爬取人人都是产品经理的数据》中有提到可以用【Copy selector】来复制粘贴出新闻来源的位置,如下第一行;也可以用本篇文章经常用到的class类的表述方法说明其位置,如下第二行;
# source = soup.select('#navtimeSource > span > span > a')[0].text
source = soup.select('.time-source span span a')[0].text
print(source)
4. 抓取新闻详情:
article = []
for p in soup.select('#artibody p')[:-1]:
article.append(p.text.strip())
# print(article)
print('\n'.join(article))
第1行:article为空列表;
第2行:通过观察代码可以发现,新闻详情存放在p标签中,如果直接输出,能看到最后一栏有责任编辑的信息,如果不想要责任编辑,增加[:-1]可以去除最后一个编辑信息;
第3行:将抓取的数据插入article列表中,.strip()去除空白信息;
第4行:可以先print下看结果是否正确,发现新闻详情的原标题和正文是在一排的,不是很好,注释掉后我们换新的方法;
第5行:join()方法用来将列表中的元素用指定的字符连接生成新的字符串,这里用\n换行来连接列表中的原标题和正文两块内容。
上面这是一种文章连接的方法,当然还有比较简洁的写法。我们将上面的for循环一句拿出来,前面加p.text.strip(),然后整体加中括号,这样就形成了一个列表,然后前面再用join将其连接起来,就用简单的一行代码替代了上面的多行代码。
print('\n'.join([p.text.strip() for p in soup.select('#artibody p')[:-1]]))
5. 抓取责任编辑:
这里用到的lstrip是去除左侧的内容,括号内‘责任编辑:’是指去除这部分内容,只保留编辑人员姓名。之前用到的strip是去除两侧,lstrip是去除左侧,后面会用到的rstrip是去除右侧内容。
editor = soup.select('.article-editor')[0].text.lstrip('责任编辑:')
print(editor)
6. 抓取评论数:
# comments = soup.select('#commentCount1')
# print(comment)
comments = requests.get('http://comment5.news.sina.com.cn/page/info?version=1&format=js&channel=gn&newsid=comos-fyeycfp9368908&group=&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=20')
# print(comments.text)
comments_total = json.loads(comments.text.strip('var data='))
# print(comments_total)
print(comments_total['result']['count']['total'])
首先,我们先select('#commentCount1')来筛选出评论数,这时print下输出结果为[<span id="commentCount1"></span>],span中间为空白信息,没有我们想要的评论数。
这时,我们需要重新去观察下网页代码,发现评论数可能是通过JavaScript来增加上去的,那么我们需要找到是从哪里调用JavaScript(即JS)的。
鼠标放在评论数(4)上,Google浏览器鼠标右键点击“检查”,选择顶部的network,然后在下面海量的链接里找到有数量4的链接。

复制该链接,中间加粗部分是newid,最后有一段像时间戳的字串“&jsvar=loader_1494295822737_91802706”,我们需要把这块内容去掉,然后试着print下,可以发现结果也不会有影响。
http://comment5.news.sina.com.cn/page/info?version=1&format=js&channel=gn&newsid=comos-fyeycfp9368908&group=&compress=0&ie=utf-8&oe=utf-8&page=1&page_size=20&jsvar=loader_1494295822737_91802706
处理好链接后,那么,我们该如何从JavaScript中读取数据呢?这时我们需要使用到json来处理,在开头,我们导入库的时候已经import json了,这里可以直接使用。
json.loads是用于解码json数据的。第5行,我们将解码后的数据存储在变量comments_total中;第6行,我们print该变量时,会得到结果,发现除了评论数之外,还有一些其他的信息。
所以我们需要重新输出,根据上一行print的结果,观察发现,最后一行我们可以用['result']['count']['total']来表示评论数的位置。
7. 抓取新闻ID:
print(news_url.split('/')[-1].rstrip('.shtml').lstrip('doc-i'))
刚在上面第6点抓取评论数时,我们发现链接中有一个newsid,该新闻页面的链接中也有相同的ID部分,这时我们可以明确其新闻ID的位置。
split()是通过指定分隔符对字符串进行切片,[-1]是截取最后一个元素,然后用rstrip去除掉末尾的.shtml,用lstrip去除掉左侧的doc-i,得到我们想要的新闻ID。
除了这种方法外,我们还可以用正则表达式来表达。这时我们需要用到re库,在开头时,我们已经事先import re了,这里直接使用。
其中re.search是扫描整个字符串并返回第一个成功的匹配,group()是匹配到的字符串,其中group(0),是匹配到的字符串全部显示(doc-ifyeycfp9368908.shtml),group(1)是(.+)内的显示,即我们想要的新闻ID。
news_id = re.search('doc-i(.+).shtml',news_url)
# print(news_id.group(0))
print(news_id.group(1))
操作环境:Python版本,3.6;PyCharm版本,2016.2;电脑:Mac
----- End -----
作者:杜王丹,微信公众号:杜王丹,互联网产品经理。

Python爬虫:抓取新浪新闻数据的更多相关文章
- 【转】Python爬虫:抓取新浪新闻数据
案例一 抓取对象: 新浪国内新闻(http://news.sina.com.cn/china/),该列表中的标题名称.时间.链接. 完整代码: from bs4 import BeautifulSou ...
- Python抓取新浪新闻数据(二)
以下是抓取的完整代码(抓取了网页的title,newssource,dt,article,editor,comments)举例: 转载于:https://blog.51cto.com/2290153/ ...
- Python爬虫抓取东方财富网股票数据并实现MySQL数据库存储
Python爬虫可以说是好玩又好用了.现想利用Python爬取网页股票数据保存到本地csv数据文件中,同时想把股票数据保存到MySQL数据库中.需求有了,剩下的就是实现了. 在开始之前,保证已经安装好 ...
- python3爬虫-爬取新浪新闻首页所有新闻标题
准备工作:安装requests和BeautifulSoup4.打开cmd,输入如下命令 pip install requests pip install BeautifulSoup4 打开我们要爬取的 ...
- php使用pthreads v3多线程的抓取新浪新闻信息
我们使用pthreads,来写一个多线程的抓取页面小程序,把结果存到数据库里. 数据表结构如下: CREATE TABLE `tb_sina` ( `id` int(11) unsigned NOT ...
- python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例
python3.4学习笔记(十四) 网络爬虫实例代码,抓取新浪爱彩双色球开奖数据实例 新浪爱彩双色球开奖数据URL:http://zst.aicai.com/ssq/openInfo/ 最终输出结果格 ...
- selenium+BeautifulSoup+phantomjs爬取新浪新闻
一 下载phantomjs,把phantomjs.exe的文件路径加到环境变量中,也可以phantomjs.exe拷贝到一个已存在的环境变量路径中,比如我用的anaconda,我把phantomjs. ...
- python 爬虫抓取心得
quanwei9958 转自 python 爬虫抓取心得分享 urllib.quote('要编码的字符串') 如果你要在url请求里面放入中文,对相应的中文进行编码的话,可以用: urllib.quo ...
- Python爬虫----抓取豆瓣电影Top250
有了上次利用python爬虫抓取糗事百科的经验,这次自己动手写了个爬虫抓取豆瓣电影Top250的简要信息. 1.观察url 首先观察一下网址的结构 http://movie.douban.com/to ...
随机推荐
- sql 一个表的字段更新至另一个字段的方法
update Lc_Taxs set TaxMember = convert(int,Lc_Taxs2.TaxNo) from Lc_Taxs a,(select * from Lc_Taxs ) ...
- gcd以及exgcd入门讲解
gcd就是最大公约数,gcd(x, y)一般用(x, y)表示.与此相对的是lcm,最小公倍数,lcm(x, y)一般用[x, y]表示. 人人都知道:lcm(x, y) = x * y / gcd( ...
- Node.js实战(四)之调试Node.js
当项目逐渐扩大以后,功能越来越多,这时有的时候需要增加或者修改,同时优化某些功能,就有可能出问题了.针对于线上Linux环境我们应该如何调试项目呢? 别怕,Node.js已经为我们考虑到了. 通过 n ...
- WinForm中Component Class、User Control及Custom Control的区别和使用
NET Framework 为您提供了开发和实现新控件的能力.除了常见的用户控件外,现在您会发现,您可以编写能执行自身绘图的自定义控件,甚至还可以通过继承扩展现有控件的功 能.确定创建何种类型的控件可 ...
- JAVA框架Struts2(二)
一:Struts2执行流程: 1)编写页面,点击超链接,请求提交到服务器端. 2)请求先经过Struts2核心过滤器(StrutsprepareAndexectuterfilter). 3)过滤器的功 ...
- java剪辑音频
用来剪辑特定长度的音频,并将它们混剪在一起,大体思路是这样的: 1. 使用 FileInputStream 输入两个音频 2. 使用 FileInputStream的skip(long n) 方法跳过 ...
- stm32_DMA采集一个AD数据_并通过DMA向串口发送
这是以前学32的时候写的,那时候学了32之后感觉32真是太强大了,比51强的没影.关于dma网上有许多的资料,关于dma采集ad网上也有很多.亲们搜搜,这里只贴代码了,其实我也想详详细细地叙述一番,但 ...
- 设置ssh key后push为什么还要输入用户名和密码
$ git push Username for 'https://github.com': Password for 'https://Username@github.com': Counting o ...
- odoo之可选择多个内容显示问题
<field name="partner_id" widget="many2many_tags" options="{'no_create': ...
- 20155330 《网络攻防》 Exp4 恶意代码分析
20155330 <网络攻防> Exp4 恶意代码分析 实验后回答问题 (1)如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监控下系统一天天的到底在干些什么.请设计下你想监控的操 ...