高校新闻抓取分析之百度新闻篇—数据清洗解析

tips:

  • 本文代码使用python3编写
  • 代码仓库
  • 使用re抓取解析数据

前言

在上一篇文章中,成功构建URL并获取到高校新闻数据。

现在将对请求回来的数据进行清洗解析,提取:新闻标题新闻来源新闻时间更多新闻链接

回顾一下新闻信息HTML片段:

<div class="result title" id="1">
•&nbsp;
<h3 class="c-title"><a href="http://www.thepaper.cn/newsDetail_forward_8438609" data-click="{'f0':'77A717EA','f1':'9F63F1E4','f2':'4CA6DE6E','f3':'54E5243F','t':'1595752997'}" target="_blank">中国科协“老科学家学术成长资料采集工程”<em>北京大学</em>联合采集启动...</a>
</h3>
<div class="c-title-author">澎湃新闻&nbsp;&nbsp;               7小时前&nbsp;&nbsp;<a href="/ns?word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29+cont:1782421700&amp;same=2&amp;cl=1&amp;tn=newstitle&amp;rn=30&amp;fm=sd" class="c-more_link" data-click="{'fm':'sd'}">查看更多相关新闻&gt;&gt;</a>
</div>
</div>
<div class="result title" id="2">
•&nbsp;
<h3 class="c-title"><a href="http://sc.people.com.cn/n2/2020/0726/c345509-34183157.html" data-click="{'f0':'77A717EA','f1':'9F63F1E4','f2':'4CA6DD6E','f3':'54E5243F','t':'1595752997'}" target="_blank"><em>北京大学</em>、清华大学等17所高校在川招生行程安排和咨询地址、电话...</a>
</h3>
<div class="c-title-author">人民网四川站&nbsp;&nbsp;             9小时前</div>
</div>

实现数据清洗

在上篇中将请求回来的数据保存为了html,方便我们进一步处理和分析。一般来说,我们提取html中有用的信息,是不需要样式和js的。所以可以预先删除这部分内容,减少干扰项。通过删除多余的空格和换行符,压缩文件。

删除script,style及空格换行符

import rewith open('test.html','r',encoding='utf-8') as f:data = f.read()
# 删除script
data = re.sub(r'<\s*script[^>]*>[^<]*<\s*/\s*script\s*>', '', data, flags=re.I)
# 删除style
data = re.sub(r'<\s*style[^>]*>[^<]*<\s*/\s*style\s*>', '', data, flags=re.I)
# 删除多余的空格及换行符
data = re.sub(r'\s{2,}', '', data)

通过上两步可以删除大部分的样式和js,但是有一部分js无法删除。那么通过下面的方式来删除,找到未能删除的js头,然后找到结束的js尾巴,循环删除这一部分即可。

while data.find('<script>') != -1:start_index = data.find('<script>')end_index = data.find('</script>')if end_index == -1:breakdata = data[:start_index] + data[end_index + len('</script>'):]

删除样式及js后压缩的html片段:

<div><div class="result title" id="1">
•&nbsp;
<h3 class="c-title"><a href="https://3g.163.com/news/article/FIG1TC630514B1BP.html"data-click="{'f0':'77A717EA','f1':'9F63F1E4','f2':'4CA6DD6E','f3':'54E5243F','t':'1595773708'}"target="_blank">在宣汉揭牌!<em>北京大学</em>文化产业博士后创新实践基地成立</a>
</h3>
<div class="c-title-author">网易&nbsp;&nbsp;3小时前&nbsp;&nbsp;<a href="/ns?word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29+cont:2675916080&same=2&cl=1&tn=newstitle&rn=30&fm=sd" class="c-more_link" data-click="{'fm':'sd'}">查看更多相关新闻>></a>
</div>
</div><div class="result title" id="2">
•&nbsp;
<h3 class="c-title"><a href="https://3g.163.com/news/article/FIFOP7BP05501E5I.html"data-click="{'f0':'77A717EA','f1':'9F63F1E4','f2':'4CA6DD6E','f3':'54E5243F','t':'1595773708'}"target="_blank">衡阳市“人大讲坛”再次开讲!听<em>北京大学</em>法学博士说“贪”</a>
</h3>
<div class="c-title-author">网易&nbsp;&nbsp;5小时前</div>
</div>

实现数据解析

1. 提取Html新闻片段

通过前面的删除多余删除样式及js并压缩后,html相对规整,接下来需要做的:

  • 正则提取出包含所有新闻的字符串
  • 移除多余的字符串
  • 字符操作分割出每条新闻html片段

代码如下:

# 取出解析的数据字符串
wait_parse_string = re.search(r'<div id="content_left">([\s\S]*)<div id="gotoPage">', data)if wait_parse_string:wait_parse_string = wait_parse_string.group()# 移除最后多余字符串wait_parse_string = re.sub(r'</div></div><div id="gotoPage">', '', wait_parse_string)flag = '<div class="result title"'flag_length = len(flag)# 遍历字符串并分割出单条新闻数据news_list = []while wait_parse_string.find('<div class="result title"') != -1:start_index = wait_parse_string.find(flag)end_index = wait_parse_string[start_index + flag_length:].find(flag)if end_index > 0:end_index = start_index + end_index + flag_lengthelse:end_index = len(wait_parse_string)news_list.append(wait_parse_string[start_index:end_index])wait_parse_string = wait_parse_string[end_index:]print(news_list)

部分结果:

['<div class="result title" id="1">\n•&nbsp;\n<h3 class="c-title"><a href="https://3g.163.com/news/article/FIG1TC630514B1BP.html"data-click="{\'f0\':\'77A717EA\',\'f1\':\'9F63F1E4\',\'f2\':\'4CA6DD6E\',\'f3\':\'54E5243F\',\'t\':\'1595773708\'}"target="_blank">在宣汉揭牌!<em>北京大学</em>文化产业博士后创新实践基地成立</a>\n</h3>\n<div class="c-title-author">网易&nbsp;&nbsp;3小时前&nbsp;&nbsp;<a href="/ns?word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29+cont:2675916080&same=2&cl=1&tn=newstitle&rn=30&fm=sd" class="c-more_link" data-click="{\'fm\':\'sd\'}">查看更多相关新闻>></a>\n</div>\n</div>']

2. 提取数据

通过上一步分割出了单条数据,将数据进一步解析,通过正则提取出需要的字段。代码如下:

from datetime import datetime, timedeltadef time_convert(time_string: str):"""标准化日期字符串:param time_string::return:"""if not time_string:return ''if '分钟前' in time_string:minute = re.search(r'\d+', time_string)if minute:minute = minute.group()now = datetime.now() - timedelta(minutes=int(minute))else:now = datetime.now()return now.strftime('%Y-%m-%d')elif '小时前' in time_string:hour = re.search(r'\d+', time_string)if hour:hour = hour.group()now = datetime.now() - timedelta(hours=int(hour))else:now = datetime.now()return now.strftime('%Y-%m-%d')else:try:parse_time = datetime.strptime(time_string, '%Y年%m月%d日 %H:%M')return parse_time.strftime('%Y-%m-%d')except Exception as e:now = datetime.now()return now.strftime('%Y-%m-%d')news_data = []
for news in news_list:temp = {"news_key": '北京大学',"news_title": '','news_link': '','news_author': '','news_time': '','more_link': '',}# 解析链接news_link = re.search(r'<a\s*href="(\S+)"\s*data-click', news, re.I)if news_link:temp["news_link"] = news_link.group(1)# 解析标题news_title = re.search(r'target="_blank">([\d\D]*)(</a>\s*</h3>)', news, re.I)if news_title:temp["news_title"] = news_title.group(1)# 解析发布者及时间author_time = re.search(r'<div class="c-title-author">(\S+)&nbsp;&nbsp;((\d+分钟前)|(\d+小时前)|(\d+年\d+月\d+日 \d+:\d+))', news, re.I)if author_time:temp["news_author"] = author_time.group(1)temp["news_time"] = time_convert(author_time.group(2))# 解析查询更多相同新闻more_link = re.search(r'<a\s*href="(\S+)"\s*class="c-more_link"', news, re.I)if more_link:temp["more_link"] = more_link.group(1)news_data.append(temp)

部分结果:

[{'news_key': '北京大学', 'news_title': '在宣汉揭牌!<em>北京大学</em>文化产业博士后创新实践基地成立', 'news_link': 'https://3g.163.com/news/article/FIG1TC630514B1BP.html', 'news_author': '网易', 'news_time': '2020-07-26', 'more_link': '/ns?word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29+cont:2675916080&same=2&cl=1&tn=newstitle&rn=30&fm=sd'},]

3. 数据存储

经过数据的从抓取和解析,已经能得到比较规整的数据。我们只需要按照一定的字段写入到数据库或者文本即可,接下来存储到非关系型数据库mongodb。需要使用到pymongo包,使用命令pip install pymongo

import pymongo
# 构建数据库连接
mongo_uri = 'mongodb://%s:%s@%s:%s/%s' % ("root", '123456', "127.0.0.1", "27017", "school_news_analysis")
conn = pymongo.MongoClient(mongo_uri)
db = conn.school_news_analysis
school_news = db.school_news
insert_data = list()
for item in news_data:# 根据链接去重,重复更新 insert_data.append(pymongo.ReplaceOne({'news_link': item['news_link']}, item, upsert=True))
school_news.bulk_write(insert_data)

4. 完整代码

import re
from datetime import datetime, timedeltaimport pymongowith open('test.html', 'r', encoding='utf-8') as f:data = f.read()
# 删除script
data = re.sub(r'<\s*script[^>]*>[^<]*<\s*/\s*script\s*>', '', data, flags=re.I)
# 删除style
data = re.sub(r'<\s*style[^>]*>[^<]*<\s*/\s*style\s*>', '', data, flags=re.I)
# 删除多余的空格及换行符
data = re.sub(r'\s{2,}', '', data)while data.find('<script>') != -1:start_index = data.find('<script>')end_index = data.find('</script>')if end_index == -1:breakdata = data[:start_index] + data[end_index + len('</script>'):]with open('test1.html', 'w', encoding='utf-8') as f:f.write(data)# 取出解析的数据字符串
wait_parse_string = re.search(r'<div id="content_left">([\s\S]*)<div id="gotoPage">', data)news_list = []
if wait_parse_string:wait_parse_string = wait_parse_string.group()# 移除最后多余字符串wait_parse_string = re.sub(r'</div></div><div id="gotoPage">', '', wait_parse_string)flag = '<div class="result title"'flag_length = len(flag)# 遍历字符串并分割出单条新闻数据while wait_parse_string.find('<div class="result title"') != -1:start_index = wait_parse_string.find(flag)end_index = wait_parse_string[start_index + flag_length:].find(flag)if end_index > 0:end_index = start_index + end_index + flag_lengthelse:end_index = len(wait_parse_string)news_list.append(wait_parse_string[start_index:end_index])wait_parse_string = wait_parse_string[end_index:]print(news_list)def time_convert(time_string: str):"""标准化日期字符串:param time_string::return:"""if not time_string:return ''if '分钟前' in time_string:minute = re.search(r'\d+', time_string)if minute:minute = minute.group()now = datetime.now() - timedelta(minutes=int(minute))else:now = datetime.now()return now.strftime('%Y-%m-%d')elif '小时前' in time_string:hour = re.search(r'\d+', time_string)if hour:hour = hour.group()now = datetime.now() - timedelta(hours=int(hour))else:now = datetime.now()return now.strftime('%Y-%m-%d')else:try:parse_time = datetime.strptime(time_string, '%Y年%m月%d日 %H:%M')return parse_time.strftime('%Y-%m-%d')except Exception as e:now = datetime.now()return now.strftime('%Y-%m-%d')news_data = []
for news in news_list:temp = {"news_key": '北京大学',"news_title": '','news_link': '','news_author': '','news_time': '','more_link': '',}# 解析链接news_link = re.search(r'<a\s*href="(\S+)"\s*data-click', news, re.I)if news_link:temp["news_link"] = news_link.group(1)# 解析标题news_title = re.search(r'target="_blank">([\d\D]*)(</a>\s*</h3>)', news, re.I)if news_title:temp["news_title"] = news_title.group(1)# 解析发布者及时间author_time = re.search(r'<div class="c-title-author">(\S+)&nbsp;&nbsp;((\d+分钟前)|(\d+小时前)|(\d+年\d+月\d+日 \d+:\d+))', news, re.I)if author_time:temp["news_author"] = author_time.group(1)temp["news_time"] = time_convert(author_time.group(2))# 解析查询更多相同新闻more_link = re.search(r'<a\s*href="(\S+)"\s*class="c-more_link"', news, re.I)if more_link:temp["more_link"] = more_link.group(1)news_data.append(temp)print(news_data)# 构建数据库连接
mongo_uri = 'mongodb://%s:%s@%s:%s/%s' % ("root", '123456', "127.0.0.1", "27017", "school_news_analysis")
conn = pymongo.MongoClient(mongo_uri)
db = conn.school_news_analysis
school_news = db.school_news
insert_data = list()
for item in news_data:# 根据链接去重,重复更新insert_data.append(pymongo.ReplaceOne({'news_link': item['news_link']}, item, upsert=True))
school_news.bulk_write(insert_data)

总结

  • 基本上完成了高校百度新闻的抓取和存储
  • 需进一步封装函数,方便后续使用,可以关注本代码库。
  • 下一步将对高校基本信息进行抓取

高校新闻抓取分析之百度新闻篇---数据清洗解析相关推荐

  1. 高校新闻抓取分析之百度新闻篇---数据抓取

    高校新闻抓取分析之百度新闻篇-数据抓取 tips: 本文代码使用python3编写 代码仓库 使用urllib抓取数据 百度新闻网页界面分析 在我读大学的时候(18年前),百度新闻还能基于新闻标题或者 ...

  2. 自动新闻抓取系统-开发有感(转载)

    转载自:http://www.zowee.cn/blog/blogArticle.aspx?id=2442&userid=2 自动新闻抓取系统,或称新闻小偷,已被很多人在使用,实现方式也多种多 ...

  3. Python3从搜狐国际新闻抓取---尝试版

    Python3从搜狐国际新闻抓取-尝试版 点击此处获取完整代码 - 依赖包版本信息 Python 3.7.2 requests 2.21.0 beautifulsoup4 4.6.3 首先下载HTML ...

  4. python 自动抓取分析房价数据——安居客版

    引言 中秋回家,顺便想将家里闲置的房子卖出去.第一次卖房,没经验,于是决定委托给中介.中介要我定个价.最近几年,房价是涨了不少,但是长期在外,也不了解行情.真要定个价,心里还没个数.网上零零散散看了下 ...

  5. python 命令行抓取分析北上广深房价数据

    引言 昨天在老家,发布了一篇<python 自动抓取分析房价数据--安居客版>.在文末,第6小节提供了完整代码,可以在 python3 环境,通过命令行传入参数 cookie 自动抓取房价 ...

  6. java 抓取百度新闻,java中使用jdom生成百度新闻抓取的xm

    百度新闻开放,详细见 plaincopy to clipboardprint? 自己用java写了个使用jdom生成百度要求的 xml文件 的实例,生成供百度搜索引擎抓取新闻 package com. ...

  7. python抓取微信公众号新闻文章图片

    在看公众号新闻的时候,总会有一些有用的PPT图片啥的想保存下来. 那么用python如何抓取来,简单介绍一下. 比如这个网址,https://mp.weixin.qq.com/s/-rj91sCpea ...

  8. python爬取腾讯新闻_Python 实现腾讯新闻抓取

    原博文 2012-08-14 09:56 − 思路: 1.抓取腾讯新闻列表页面: http://news.qq.com/ 2.提取详细页面的url:http://news.qq.com/a/20120 ...

  9. 抓取汽车之家新闻资讯做安卓app新闻资讯数据

    //2016/09/16/// //by   xbw/// 抓取服务器端php源码 <?PHP set_time_limit(0); require("db_config.php&qu ...

最新文章

  1. ViewPager,TabLayout,Fragment实现tabs滑动
  2. php正则的练习(持续跟新)
  3. 用canvas绘制一个圆形,实现绕着一个中心运动
  4. 浅谈三种特殊进程:孤儿进程,僵尸进程和守护进程
  5. SSO单点登录学习总结(2)——基于Cookie+fliter单点登录实例
  6. GO超详细基础语法黑点
  7. glide源码中包含了那种设计模式_Glide源码解读(一)
  8. SAP VA01 消息 没有用于售达方 XXXXXX 的客户主记录存在
  9. 微信小程序下拉刷新事件无效原因
  10. 工业级POE交换机、企业级交换机、普通交换机之间各区别?
  11. 广义根轨迹 matlab,根轨迹心得体会
  12. 【网易笔试】小易最近在数学课上学习到了集合的概念
  13. 操作系统课程设计--简单文件系统的实现
  14. 【毕业设计_课程设计】在线免费小说微信小程序的设计与实现(源码+论文)
  15. 一场疫情,全民变厨子、医生变战士、教师变主播、只有孩子们,依然是神兽!...
  16. 【文学文娱】《有用无用论》
  17. java 阿拉伯语_用Java排序阿拉伯语单词
  18. 设计模式-工厂模式(详细)
  19. proxysql mysql_利用ProxySQL实现MySQL的读写分离
  20. TiDB集群部署最细化教程-亲测有效

热门文章

  1. 精品国创《少年歌行》数字藏品开售,邀你共铸少年武侠江湖梦
  2. 分享个网站,用Python批量采集4K壁纸【Python采集壁纸系列一】
  3. 学生HTML个人网页作业作品下载 HTML5+CSS大作业——个人网页(4页)
  4. 我与世界杯足球那些事——世界杯征文
  5. 软路由折腾日记(一)
  6. Java 汉字拆分转为拼音 及根据经纬度获取所在位置
  7. Intra-LTE Handover : X2 based handover
  8. 20年了啊:那年冬天
  9. 《逻辑哲学论》 (最后部分节选)
  10. 频谱分析仪分辨率带宽到底是什么?