前言
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。
不管你是零基础还是有基础都可以获取到自己相对应的学习礼包!包括Python软件工具和2020最新入门到实战教程。加群695185429即可免费获取。
1 提取百度新闻标题、网址、日期及来源
1.1 获取网页源代码
我们通过如下代码可以获取网页源代码,示例中代码是获取在百度新闻中搜索阿里巴巴的网页源代码。
import requests headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/77.0.3865.120 Safari/537.36'} res = requests.get(url, headers=headers) web_text = res.text
因为百度新闻网站只认可浏览器发送的请求,所以需要设置headers参数,以模拟浏览器的发送请求,chrome浏览器可以通过about:version获取。
1.2 编写正则表达式提取新闻信息
1.2.1 提取新闻的来源和日期
通过观察网页源码,我们发现每条新闻的来源和发布日期都夹在<p class="c-author">和</p>之间,因此,可以通过正则表达式获取中间的来源和日期信息。
pattern = '<p class="c-author">(.*?)</p>' info = re.findall(pattern, web_text, re.S) # re.S用于考虑换行符,因为.和*不包含换行符 print(info)
获取的信息中包含了很多诸如空格、换行符、制表符以及<img>标签的内容,需要对数据进行二次清洗,这部分内容将在后面章节介绍到。
1.2.2 提取新闻的网址和标题。
为了提取新闻网址和标题,需要像上节那样从网页源码中发现规律,通过获取的源码,我们发现,新闻地址前面都有<h3 class="c-title">。
通过如下两段代码,可以分别获取新闻的网址和标题。
pattern_herf = '<h3 class="c-title">.*?<a href="(.*?)"' herf = re.findall(pattern_herf, web_text, re.S) print(herf) pattern_title = '<h3 class="c-title">.*?>(.*?)</a>' title = re.findall(pattern_title, web_text, re.S) print(title)
获取的数据同样需要进行二次数据清洗。
1.2.3 数据清洗
-
新闻标题清洗
提取的新闻标题数据存在两个问题:一是每个标题的收尾含有换行符和一些空格;二是中间含有<em>和</em>等无效字符。
(1)通过stip()函数把不需要的空格和换行符去掉。
for i in range(len(title)): title[i] = title[i].strip()
2)用sub()函数处理<em>和</em>
for i in range(len(title)): title[i] = title[i].strip() title[i] = re.sub('<.*?>', '', title[i])
2 新闻来源和日期清理
提取的新闻来源和日期中存在的问题:夹杂着很多<imag>标签信息;新闻来源和日期连在一起;夹杂着很多换行符、制表符、空格符等
for i in range(len(info)): info[i] = re.sub('<.*?>', '', info[i]) # 清洗<img>标签信息 source.append(info[i].split(' ')[0]) # 将新闻来源和日期分开 date.append(info[i].split(' ')[1]) source[i] = source[i].strip() date[i] = date[i].strip()
2. 批量获取多家公司的百度新闻并生成数据报告
本章主要实现批量获取多家公司的信息,并自动生成数据报告,导出为一个文本文件
2.1 批量爬取多家公司的百度新闻
这里,我们将爬取网页的工作封装成一个函数。
def baidu_news(company): """ 获取网页源码,并提取百度新闻标题、网址、日期和来源 :param company: 公司名称 :return: 网页源码 """ url = 'https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&word=' + company # 百度新闻网站只认可浏览器发送的请求,所以需要设置headers参数, # 以模拟浏览器的发送请求,chrome浏览器可以通过about:version获取 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/77.0.3865.120 Safari/537.36'} res = requests.get(url, headers=headers) web_text = res.text # 获取新闻的来源和日期 pattern = '<p class="c-author">(.*?)</p>' info = re.findall(pattern, web_text, re.S) # re.S用于考虑换行符,因为.和*不包含换行符 # print(info) # 获取新闻的网址和标题 pattern_herf = '<h3 class="c-title">.*?<a href="(.*?)"' herf = re.findall(pattern_herf, web_text, re.S) # print(herf) pattern_title = '<h3 class="c-title">.*?>(.*?)</a>' title = re.findall(pattern_title, web_text, re.S) # print(title) # title 数据清洗 for i in range(len(title)): title[i] = title[i].strip() title[i] = re.sub('<.*?>', '', title[i]) # print(title) # 新闻来源和日期清洗 source = [] date = [] for i in range(len(info)): info[i] = re.sub('<.*?>', '', info[i]) # 清洗<img>标签信息 source.append(info[i].split(' ')[0]) # 将新闻来源和日期分开 date.append(info[i].split(' ')[1]) source[i] = source[i].strip() date[i] = date[i].strip() print(str(i+1) + '.' + title[i] + '(' + date[i] + '-' + source[i] + ')')
然后再主函数中编写调用过程。
companys = ['华能信托', '腾讯', '阿里巴巴'] for company in companys: baidu_news(company) print(company + '百度新闻爬取成功')
结果如下所示:
1.信托业绩哪家强?两家去年净利超30亿 华宸华融有点“惨淡”(2020年01月21日 23:38-每日经济新闻)
2.57家信托业绩哪家强?中信、华能、重庆信托稳坐前三(2020年01月20日 07:47-新浪财经)
3.2019年净利润排位确定:中信信托35.93亿独占鳌头(2020年01月16日 16:51-金融界)
4.关于为“华能信托-链融科技诚意2期供应链金融资产支持专项计划”...(2020年01月16日 23:10-金融界)
5.2019信托公司业绩哪家强?(2020年01月17日 19:53-中国金融新闻网)
6.去年信托调研185家上市公司 电子设备制造业成为重点(2020年01月06日 10:07-中国基金会网)
7.关于为“华能信托-一方诚意3期供应链金融资产支持专项计划”提供...(2020年01月06日 23:10-新浪)
8.牧原股份联合华能信托 拟72亿元设立两家养猪子公司(2019年12月11日 22:28-同花顺财经)
9.牧原股份生猪养殖多地开花 借力华能信托找钱(2019年12月11日 10:32-财新)
10.牧原股份(002714.SZ)与华能贵诚信托设立的合资公司已注册成立(2019年12月12日 21:09-新浪)
华能信托百度新闻爬取成功
1.广东首例N95口罩诈骗案告破 腾讯协助警方破案(1小时前-中国新闻网)
2.抗击疫情 腾讯联合微医等五平台提供义诊服务(1小时前-新浪)
3.腾讯联合五大平台,在线义诊新型肺炎(1小时前-手机凤凰网)
4.腾讯文档开放免费会员,全面支持远程办公(4小时前-新浪)
5.最惨游戏工作室!13年9款神作却穷得叮当响,腾讯看中后出手了(1小时前-17173游戏网)
6.音乐战“疫”进行时 TME腾讯音乐人踊跃创作公益歌曲“声”援武汉(54分钟前-腾讯科技)
7.如果说国行NS不是腾讯和任天堂合作的重点,那什么是重点?(1小时前-新浪)
8.腾讯云向黄牛教授实验室,罗海彬教授团队提供免费云超算等(23分钟前-钛媒体)
9.停课不停学 腾讯课堂助力重庆十一中高三线下课首次线上开课(6小时前-环球网)
10.腾讯文档开放免费会员功能 协同编辑人数至200人(50分钟前-中关村在线)
腾讯百度新闻爬取成功
1.阿里巴巴全球14国直采医疗物资驰援,将通过东方航空陆续抵汉(39分钟前-武汉发布)
2.阿里巴巴全球采购医疗物资 首批N95口罩今日运抵武汉(29分钟前-浙江新闻)
3.阿里巴巴与东航合力 在14国采购与运输医疗物资(1小时前-新浪)
4.阿里巴巴全球采购医疗物资陆续抵沪(48分钟前-同花顺财经)
5.阿里巴巴一纸“禁令”后,商家祭出高仿口罩!抓住这点、一招鉴别(9分钟前-IT爆料王)
6.阿里巴巴等百家企业承诺:防疫、民生用品价格不涨(6小时前-TechWeb)
7.【阿里巴巴等多个企业共同发出“三保行动 让我们一起出发”的倡议】(5小时前-新浪)
8.阿里巴巴上线发热门诊查询 已覆盖5734个发热门诊(2020年01月29日 11:10-中国新闻网)
9.武汉疫情口罩脱销,阿里巴巴发出紧急通知,这种口罩不能买!(1小时前-科技季节)
10.阿里巴巴等多家企业响应市场监管总局“三保”行动(2020年01月29日 23:47-新浪财经)
阿里巴巴百度新闻爬取成功
2.2 自动生成舆情数据报告文本文件
上一节已经爬取到了我们想要的新闻,并生成了舆情结果,下面将其导出到文本文件中。
在baidu_news()函数后面增加导出到文件的相关操作代码如下:
file_ = open('数据挖掘报告.txt', 'a') #追加模式,不清除原来的数据 file_.write(company + '新闻数据:' + '\n' + '\n') for i in range(len(title)): file_.write(str(i+1) + '.' + title[i] + '(' + date[i] + '-' + source[i] + ')' + '\n') file_.write(href[i] + '\n') file_.write('————————————————————————————————————————————' + '\n' + '\n') file_.close()
3. 异常处理及24小时实时数据挖掘实战
3.1 异常处理
这里需要对函数baidu_news()的执行进行异常处理。
companys = ['华能信托', '腾讯', '阿里巴巴'] for company in companys: try: baidu_news(company) print(company + '百度新闻爬取成功!') except: print(company + '百度新闻爬取失败!')
3.2 24小时实时爬取
这个功能的实现比较简单,只需要在程序外面套一层while True循环即可,然后可以在每一次循环执行之后,引用time库,执行time.sleep()函数来让程序每隔一段时间执行一次。
通过前面的代码,我们已经能够实现24小时不间断获取新闻内容,但是这里面不可避免的会爬取到重复的新闻数据,这就涉及到数据去重的内容,需要用到数据库的相关知识,这部分内容将在后面的章节进行介绍,感兴趣的读者可以继续关注。
4. 按时间顺序爬取及批量爬取多页内容
前面的章节仅仅是爬取了百度新闻搜索结果的第一个页面的内容,消息数据不全面,本章将会介绍批量爬取多页内容的方法。
4.1 按时间顺序爬取百度新闻
这里不涉及代码修改的内容,因为百度新闻默认是按照“按焦点顺序”排列新闻内容,这里我们可以在搜索结果页面的右上角选择“按时间排序”按钮,然后修改一下url即可。
4.2 一次性批量爬取多页内容
如果要实现爬取多页内容,我们需要分析每一页网址的差别。
第一页内容的网址为:
https://www.baidu.com/s?tn=news&rtt=1&bsst=1&cl=2&wd=阿里巴巴
第二页内容的网址为
https://www.baidu.com/s?tn=news&rtt=1&bsst=1&cl=2&wd=阿里巴巴&pn=10
第二页内容的网址为。
https://www.baidu.com/s?tn=news&rtt=1&bsst=1&cl=2&wd=阿里巴巴&pn=20
通过对比可以发现,页面网址之间的差别就在&pn=XX,这里可以确定第一页的网址后面可以加上内容&pn=0,因此,可以对代码进行如下修改。
def baidu_news(company, page): """ 获取网页源码,并提取百度新闻标题、网址、日期和来源 :param company: 公司名称 :param page: 需要爬取的页面的数量 :return: 网页源码 """ num = (page - 1) * 10 url = 'https://www.baidu.com/s?rtt=1&bsst=1&cl=2&tn=news&word=' + company + '&pn=' + str(num) res = requests.get(url, headers=headers, timeout=10) web_text = res.text # 此处省略了数据提取、清洗和爬取的代码 def main(): companys = ['华能信托', '腾讯', '阿里巴巴'] for company in companys: for i in range(5): # 爬取5页内容 try: baidu_news(company, i+1) print(company + str(i+1) + '页新闻爬取成功!') except: print(company + str(i+1) + '页新闻爬取失败!')
5. 搜狗新闻与新浪财经数据挖掘实战
这里采取的方法与爬取百度新闻的方法类似。
5.1 搜狗新闻数据爬取
-
首先获取搜狗新闻的网址,我们在搜狗新闻中搜索“阿里巴巴”,获得网址为(经过删减):
https://news.sogou.com/news?query=阿里巴巴
完整代码如下:
""" 作者:Aidan 时间:30/01/2020 功能:爬取搜狗新闻数据 """ import requests import re # 百度新闻网站只认可浏览器发送的请求,所以需要设置headers参数, # 以模拟浏览器的发送请求,chrome浏览器可以通过about:version获取 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/77.0.3865.120 Safari/537.36'} def sougou_news(company, page): """ 获取网页源码,并提取搜狗新闻标题、网址、日期和来源 :param company: 公司名称 :param page: 需要爬取的页面的数量 :return: 网页源码 """ url = 'https://news.sogou.com/news?query=' + company + '&page=' + str(page) res = requests.get(url, headers=headers, timeout=10) # 当访问网址10秒没有响应时,就会停止访问。timeout=10 web_text = res.text # 获取新闻日期 pattern_date = '<p class="news-from">.*? (.*?)</p>' date = re.findall(pattern_date, web_text, re.S) # re.S用于考虑换行符,因为.和*不包含换行符 # print(info) # 获取新闻的网址和标题 pattern_herf = '<h3 class="vrTitle">.*?<a href="(.*?)"' href = re.findall(pattern_herf, web_text, re.S) # print(href) pattern_title = '<h3 class="vrTitle">.*?>(.*?)</a>' title = re.findall(pattern_title, web_text, re.S) # print(title) # 数据清洗 for i in range(len(title)): title[i] = re.sub('<.*?>', '', title[i]) title[i] = re.sub('&.*?;', '', title[i]) date[i] = re.sub('<.*?>', '', date[i]) file_ = open('搜狗数据挖掘报告.txt', 'a') #追加模式,不清除原来的数据 file_.write(company + str(i+1) + '页新闻数据:' + '\n' + '\n') for i in range(len(title)): file_.write(str(i+1) + '.' + title[i] + '(' + date[i] + ')' + '\n') file_.write(href[i] + '\n') file_.write('————————————————————————————————————————————' + '\n' + '\n') file_.close() def main(): companys = ['华能信托', '腾讯', '阿里巴巴'] for company in companys: for i in range(5): # 爬取5页内容 try: sougou_news(company, i+1) print(company + str(i+1) + '页新闻爬取成功!') except: print(company + str(i+1) + '页新闻爬取失败!') if __name__ == '__main__': main()