版权声明:本文为博主AzureSky原创文章,转载请注明出处:http://www.cnblogs.com/jiayongji/p/7420915.htmlhtml
每一年我国政府都会发布年度政府工做报告,而报告中出现最多的TopN关键词都会成为媒体热议的焦点,更是体现了过去一年和将来政府工做的重点和趋势。python
在中央政府网站上也能够看到从1954年至今每一年的政府工做报告,连接:http://www.gov.cn/guoqing/2006-02/16/content_2616810.htmgit
那么突发奇想,从这60多年间的政府工做报告中能够看出来什么样的变迁呢?说干就干,下面就是实现这一想法的历程。github
获取1954年至今历年政府工做报告的全文,并统计出每一年政府工做报告中Top20的关键词,并用图表可视化展现出来。web
统计每十年的政府工做报告的合并Top20关键词,并用图表直观展现出来,从中分析出变迁的趋势。json
数据获取阶段须要有两个准备:app
2017年政府工做报告连接:http://www.gov.cn/premier/2017-03/16/content_5177940.htm函数
1954~2017年政府工做报告汇总页面连接:http://www.gov.cn/guoqing/2006-02/16/content_2616810.htm工具
使用很是好用的web库——requests获取网页内容。字体
使用BeautifulSoup库解析网页HTML内容,从中解析出政府工做报告的文本内容。
使用结巴分词库(jieba)对政府工做报告文本内容进行分词、过滤无效词、统计词频。
使用matplotlib库画出每十年政府工做报告关键词的散点分布图,经过对比不一样年代的图,分析其中的变化趋势。
准备工做作好后,咱们开始按照计划一步步地开始实施。
为了代码复用,建立一个html_utils.py文件,提供下载网页内容的函数,并提供了一个HTML页面解析异常类:
# coding:utf-8 # html工具函数 import requests # 通用请求Hearders HEADERS = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36'} # html页面解析异常 class HtmlParseError(Exception): def __init__(self,value): self.value = value def __str__(self): return repr(self.value) # 获取网页页面html全文 def get_html(url): resp = requests.get(url,headers = HEADERS) resp.encoding = 'utf-8' if resp: return resp.text return None
咱们的整体思路是先获取网页内容,而后从网页内容中解析出政府工做报告正文,而后对其进行分词,这里分词须要用到jieba模块,咱们建立一个cut_text_utils.py文件,在其中提供分词的函数,内容以下:
# coding:utf-8 # 分词操做工具函数 import sys import jieba from collections import Counter # 对一段文本进行分词,并过滤掉长度小于2的词(标点、虚词等),用全模式分词 def cut_text(text): cut_list = jieba.cut(text.lower()) return [word for word in cut_list if len(word) >= 2] # 统计出一段文本中出现数量最多的前n个关键词及数量 def get_topn_words(text,topn): cut_list = cut_text(text) counter = Counter(cut_list) return counter.most_common(topn) if __name__ == '__main__': # 设置字节流编码方式为utf-8 reload(sys) sys.setdefaultencoding('utf-8') s = u'我想和女友一块儿去北京故宫博物院参观和闲逛。' # print cut_text(s) print get_topn_words(s,5)
运行上述Demo脚本,输出:
[(u'参观', 1), (u'北京故宫博物院', 1), (u'一块儿', 1), (u'女友', 1), (u'闲逛', 1)]
最终要使用matplotlib库绘出关键词的散点图,能够更直观地进行分析,因此咱们再写一个绘图工具文件visual_utils.py,内容以下:
# coding:utf-8 import matplotlib.pyplot as plt # 指定默认字体,防止画图时中文乱码 plt.rcParams['font.sans-serif'] = ['SimHei'] # 传入一组关键词及词频列表,从高到低绘出每一个关键词频率的散点图 # keywords示例:[(u'张三',10),(u'李四',12),(u'王五',7)] def draw_keywords_scatter(keywords,title = None,xlabel = None,ylabel = None): # 先对keywords按词频从高到低排序 keywords = sorted(keywords,key = lambda item:item[1],reverse = True) # 解析出关键词列表 words = [x[0] for x in keywords] # 解析出对应的词频列表 times = [x[1] for x in keywords] x = range(len(keywords)) y = times plt.plot(x, y, 'b^') plt.xticks(x, words, rotation=45) plt.margins(0.08) plt.subplots_adjust(bottom=0.15) # 图表名称 plt.title(title) # x,y轴名称 plt.xlabel(xlabel) plt.ylabel(ylabel) plt.show() def main(): draw_keywords_scatter([(u'张三',10),(u'李四',12),(u'王五',7)],u'出勤统计图',u'姓名',u'出勤次数') if __name__ == '__main__': main()
运行上面的Demo脚本,绘图结果以下:
接下来咱们先获取到2017年的政府工做报告试试水,建立一个文件year2017_analysis.py,内容以下:
# coding:utf-8 # 分析2017年政府工做报告,从中提取出前20个高频词 import sys from bs4 import BeautifulSoup as BS import html_utils import cut_text_utils # 2017年政府工做报告全文URL REPORT_URL = 'http://www.gov.cn/premier/2017-03/16/content_5177940.htm' # 从2017年政府工做报告html页面内容中解析出正文 def parse_report_article(html): soup = BS(html,'html.parser') article = soup.find('div',attrs = {'id':'UCAP-CONTENT'}) # 报告正文,这里能够经过分析网页HTML结构获取到解析的方法 return article.text # 传入2017年政府工做报告全文的URL,解析出topn关键词及词频 def get_topn_words(url,topn): html = html_utils.get_html(url) article = parse_report_article(html) return cut_text_utils.get_topn_words(article,topn) def main(): # 设置字节流编码方式为utf-8 reload(sys) sys.setdefaultencoding('utf-8') with open('out.tmp','w+') as fout: fout.write(str(get_topn_words(REPORT_URL,20))) if __name__ == '__main__': main()
运行上述脚本,而后在当前目录下能够看到产生了一个out.tmp文件,其内容以下:
[(u'发展', 125), (u'改革', 68), (u'推动', 65), (u'建设', 54), (u'经济', 52), (u'增强', 45), (u'推进', 42), (u'加快', 40), (u'政府', 39), (u'创新', 36), (u'完善', 35), (u'全面', 35), (u'企业', 35), (u'促进', 34), (u'提升', 32), (u'就业', 31), (u'实施', 31), (u'中国', 31), (u'工做', 29), (u'支持', 29)]
从中能够看出2017年的前五关键词是:发展,改革,推动,建设,经济,和咱们常常在媒体上看到的状况也比较吻合。
思路是这样的,首先从汇总页面获取到每一年政府工做报告网页的连接,而后分别爬取每一个连接获取到网页内容,接着解析出每一年的政府工做报告正文,最后对每10年的政府工做报告合并分析出Top20关键词并展现出来。
导包:
# coding:utf-8 # 1954~2017年政府工做报告汇总分析 import sys import json from collections import OrderedDict from bs4 import BeautifulSoup as BS import html_utils from html_utils import HtmlParseError import cut_text_utils
汇总页面URL:
# 汇总URL SUMMARY_URL = 'http://www.gov.cn/guoqing/2006-02/16/content_2616810.htm'
从汇总页面解析出每一年政府工做报告全文页面的URL列表:
# 从汇总页面解析出每一年政府工做报告全文页面的URL # 注:只有2017年的页面URL是专题页面而非全文页面 def get_report_urls(summary_url): html = html_utils.get_html(summary_url) soup = BS(html,'html.parser') reports_table = soup.select('#UCAP-CONTENT table tbody')[0] reports = [(atag.text,atag['href']) for trtag in reports_table.select('tr') for tdtag in trtag.select('td') if len(tdtag.select('a')) != 0 for atag in tdtag.select('a')] # 过滤去2017年的URL report_urls = [x for x in reports if x[0] != '2017'] report_urls.append(('2017',REPORT2017_URL)) # 按照年份升序排序 report_urls = sorted(report_urls,key = lambda item:item[0]) return report_urls
从报告正文页面html中解析出正文内容:
注:这里要考虑两种不一样的页面结构进行解析。
# 从报告页面html中解析出正文内容 # 考虑到不一样年份报告的2种不一样的html结构,采用两种解析方案 def parse_report_article(html): soup = BS(html,'html.parser') # 解析方案1 article = soup.select('#UCAP-CONTENT') # 若article为空,则换方案2来解析 if len(article) == 0: article = soup.select('.p1') # 若还为空,则抛出异常 if len(article) == 0: raise HtmlParseError('parse report error!') return article[0].text
经过上述函数结合使用,能够爬取到1954年到2017年的全部政府工做报告的文本,总字数为100万零7000多字。
接着如下几个函数用来解析关键词:
# 传入某一年政府工做报告全文的URL,解析出topn关键词及词频 def get_topn_words(url,topn): html = html_utils.get_html(url) article = parse_report_article(html) return cut_text_utils.get_topn_words(article,topn) # 传入若干个政府工做报告全文的URL,解析出合并topn关键词 # save_reports:是否保存文本到文件中(reports.txt) def get_topn_words_from_urls(urls,topn,save_reports = False): htmls = [html_utils.get_html(url) for url in urls] # 汇总文本 summary_atricle = '\n'.join([parse_report_article(html) for html in htmls]) if save_reports: with open('reports.txt','w+') as fout: fout.write(summary_atricle) return cut_text_utils.get_topn_words(summary_atricle,topn) # 根据传入的每一年的政府工做报告全文URL,解析出每一年的topn关键词 def get_topn_words_yearly(report_urls,topn): keywords = OrderedDict() # 遍历url列表,解析出每一年政府工做报告的top30关键词并存入字典keywords for year,url in report_urls: print 'start to parse {year} report...'.format(year = year) keywords[year] = get_topn_words(url,topn) return keywords # 根据传入的每一年的政府工做报告全文URL,解析出每一个十年的合并topn关键词 def get_topn_words_decadal(report_urls,topn): # 统计出每一个10年的topn关键词 decade1 = ['1964','1960','1959','1958','1957','1956','1955','1954'] decade2 = ['1987','1986','1985','1984','1983','1982','1981','1980','1979','1978','1975'] decade3 = ['1997','1996','1995','1994','1993','1992','1991','1990','1989','1988'] decade4 = ['2007','2006','2005','2004','2003','2002','2001','2000','1999','1998'] decade5 = ['2017','2016','2015','2014','2013','2012','2011','2010','2009','2008'] keywords = OrderedDict() decade_items = [('1954-1964',decade1),('1975-1987',decade2),('1988-1997',decade3),('1998-2007',decade4),('2008-2017',decade5)] for years,decade in decade_items: print 'start to parse {years} reports...'.format(years = years) urls = [item[1] for item in report_urls if item[0] in decade] keywords[years] = get_topn_words_from_urls(urls,topn) return keywords
汇总以上代码,合并为summary_analysis.py文件,内容以下:
# coding:utf-8 # 1954~2017年政府工做报告汇总分析 import sys import json from collections import OrderedDict from bs4 import BeautifulSoup as BS import html_utils from html_utils import HtmlParseError import cut_text_utils import visual_utils # 汇总URL SUMMARY_URL = 'http://www.gov.cn/guoqing/2006-02/16/content_2616810.htm' # 2017年政府工做报告全文URL REPORT2017_URL = 'http://www.gov.cn/premier/2017-03/16/content_5177940.htm' # 从汇总页面解析出每一年政府工做报告全文页面的URL # 注:只有2017年的页面URL是专题页面而非全文页面 def get_report_urls(summary_url): html = html_utils.get_html(summary_url) soup = BS(html,'html.parser') reports_table = soup.select('#UCAP-CONTENT table tbody')[0] reports = [(atag.text,atag['href']) for trtag in reports_table.select('tr') for tdtag in trtag.select('td') if len(tdtag.select('a')) != 0 for atag in tdtag.select('a')] # 过滤去2017年的URL report_urls = [x for x in reports if x[0] != '2017'] report_urls.append(('2017',REPORT2017_URL)) # 按照年份升序排序 report_urls = sorted(report_urls,key = lambda item:item[0]) return report_urls # 从报告页面html中解析出正文内容 # 考虑到不一样年份报告的2种不一样的html结构,采用两种解析方案 def parse_report_article(html): soup = BS(html,'html.parser') # 解析方案1 article = soup.select('#UCAP-CONTENT') # 若article为空,则换方案2来解析 if len(article) == 0: article = soup.select('.p1') # 若还为空,则抛出异常 if len(article) == 0: raise HtmlParseError('parse report error!') return article[0].text # 传入某一年政府工做报告全文的URL,解析出topn关键词及词频 def get_topn_words(url,topn): html = html_utils.get_html(url) article = parse_report_article(html) return cut_text_utils.get_topn_words(article,topn) # 传入若干个政府工做报告全文的URL,解析出合并topn关键词 # save_reports:是否保存文本到文件中(reports.txt) def get_topn_words_from_urls(urls,topn,save_reports = False): htmls = [html_utils.get_html(url) for url in urls] # 汇总文本 summary_atricle = '\n'.join([parse_report_article(html) for html in htmls]) if save_reports: with open('reports.txt','w+') as fout: fout.write(summary_atricle) return cut_text_utils.get_topn_words(summary_atricle,topn) # 根据传入的每一年的政府工做报告全文URL,解析出每一年的topn关键词 def get_topn_words_yearly(report_urls,topn): keywords = OrderedDict() # 遍历url列表,解析出每一年政府工做报告的top30关键词并存入字典keywords for year,url in report_urls: print 'start to parse {year} report...'.format(year = year) keywords[year] = get_topn_words(url,topn) return keywords # 根据传入的每一年的政府工做报告全文URL,解析出每一个十年的合并topn关键词 def get_topn_words_decadal(report_urls,topn): # 统计出每一个10年的topn关键词 decade1 = ['1964','1960','1959','1958','1957','1956','1955','1954'] decade2 = ['1987','1986','1985','1984','1983','1982','1981','1980','1979','1978','1975'] decade3 = ['1997','1996','1995','1994','1993','1992','1991','1990','1989','1988'] decade4 = ['2007','2006','2005','2004','2003','2002','2001','2000','1999','1998'] decade5 = ['2017','2016','2015','2014','2013','2012','2011','2010','2009','2008'] keywords = OrderedDict() decade_items = [('1954-1964',decade1),('1975-1987',decade2),('1988-1997',decade3),('1998-2007',decade4),('2008-2017',decade5)] for years,decade in decade_items: print 'start to parse {years} reports...'.format(years = years) urls = [item[1] for item in report_urls if item[0] in decade] keywords[years] = get_topn_words_from_urls(urls,topn) return keywords def main(): # 设置字节流编码方式为utf-8 reload(sys) sys.setdefaultencoding('utf-8') # 按年代分析每10年的政府工做报告 report_urls = get_report_urls(SUMMARY_URL) keywords = get_topn_words_decadal(report_urls,20) # 将结果保存到文件 with open('out.tmp','w+') as fout: for years,words in keywords.items(): fout.write('【{years}】\n'.format(years = years.decode('unicode-escape').encode('utf-8'))) for word,count in words: fout.write('{word}:{count};'.format(word = word,count = count)) fout.write('\n\n') # 绘出散点图 for years,words in keywords.items(): visual_utils.draw_keywords_scatter(words[:20],u'{years}年政府工做报告关键词Top{topn}'.format(years = years,topn = 20),u'关键词',u'出现总次数') if __name__ == '__main__': main()
运行该文件,在当前目录下的out.tmp文件能够看到其内容以下:
【1954-1964】
咱们:932;人民:695;国家:690;我国:664;建设:650;发展:641;社会主义:618;生产:509;工业:491;农业:481;工做:396;增加:385;增长:376;必须:361;计划:339;已经:328;方面:299;进行:298;全国:295;企业:267;
【1975-1987】
发展:1012;咱们:1011;经济:875;建设:664;我国:609;企业:586;人民:577;国家:569;社会主义:535;改革:499;工做:488;生产:486;必须:451;提升:368;增加:349;方面:349;进行:349;问题:320;增长:290;增强:288;
【1988-1997】
发展:1182;经济:789;建设:696;改革:537;工做:495;增强:485;企业:485;继续:455;国家:435;社会:432;咱们:399;我国:378;社会主义:350;积极:340;进一步:334;人民:331;提升:311;政府:289;增长:276;必须:275;
【1998-2007】
发展:814;建设:597;增强:536;经济:459;工做:430;改革:402;企业:368;继续:320;社会:287;政府:284;推动:261;增长:245;加快:240;积极:240;进一步:236;坚持:228;咱们:221;提升:217;农村:207;管理:203;
【2008-2017】
发展:1115;建设:597;经济:554;推动:507;改革:479;增强:456;社会:345;加快:344;政府:320;提升:312;实施:301;促进:301;咱们:294;工做:287;制度:272;增加:259;完善:248;政策:240;就业:240;企业:240;
同时也绘出了5张图,分别以下:
从以上5张图能够看出,1954~1964年间,“咱们”是绝对的关键词,其次第二梯队是:人民,国家,我国,建设,发展,社会主义,第三梯队是:生产,工业,农业,从中能够感觉到鲜明的时代气息。
到了1978年改革开放及其后的十年间,“发展”成为了绝对的关键词,而第二梯队的关键词是:经济,建设,我国,企业...“生产”也是提到的次数不少的关键词。
1988~1997这十年间,“发展”依然是绝对的关键词,而第二梯队的关键词基本仍是:经济,建设,改革,企业....
1998~2007是进入新世纪的十年,“发展”的主旋律依然没有变化,“农村”这一关键词进入前20,体现国家对农业的重视。印象中也就是在这几年间国家取消了延续了2000多年历史的农业税,今后不用再“交公粮”了。
再看最近的十年:2008~2017,“发展”依然是第一要务,而“制度”、“政策”、“就业”等关键词进入前20,具备新时代的特点。
https://github.com/dnxbjyj/py-project/blob/master/gov_work_report_analysis/reports-bak.txt