想法
今天又不务正业了。
早上无意中看到了一个词云图,就想要是我也能做就好了。接着就上网搜索了一下,原来用Python也能做,而且也不是很难。于是就来了一个主意:要是能够每天,将新浪要闻的内容自动爬下来,生成一个词云图,应该很好玩。
学习
想法明确了,第二步就是先学习。要实现目标,主要需要两个步骤。一是要想办法从新浪网新闻中爬出所有要闻的标题和内容,存放在文本文件中。第二个步聚就是将中文文本文件中的词提出来,按频率制作词云图。技术不懂不要紧,我问了度娘,找到了两篇相关主题的好文章,一个是博主Frange的 python用requests爬取新浪财经首页要闻 和博主温润有方的python3 wordcloud词云。这两个文单都写得特别好,果断收入印象笔记中,认真学习,并且做了费曼笔记。对其中看不懂的,例如lxml.etree,也是问百度对各个知识点各个击破。以前有一点点基础,两个小时以后,也就差不多弄懂了。他们的代码也很棒,我就不重复造轮子,很多代码在后就直接引用了。我后面的内容与得很简略,对这个主题感兴趣的请直接点击看大神的原文。
准备工作
- 安装Python 3 ,建议用Anaconda安装
- 安装Sublime
- 安装第三方库
requests模块,
lxml模块
jieba模块
WordCloud模块 - 找个图片做为词云背景图,我百度了个中国地图
实现
-
打开新浪新闻网首页http://news.sina.com.cn , 右击要闻内的新闻,检查元素(Edge浏览器), 我们得知要闻的div的id="syncad_1"。 所有要闻的url都存在于该div下面。
思路:
2.1 用requests.get打开网页,然后用xpath("//div[@id='syncad_1']//a//@href")解析出所有重要新闻的网址url
2.2 一个一个地打开要闻的url, 分别用xpath('//h1/text()')[0]和xpath('//div[@class="article"]/p//text()')打开文章的标题和内容,然后存入news.txt文件中。
2.3 打开news.txt文件内容,使用jieba.cut_for_search将中文文本文件内容切分成词组,并存入一个list中。
2.4 使用wordcloud,制作词云图。其中我们使用了test.jpg(一个中国地图)来设定了词云图的样子。
2.5 将词云图存入test.png中代码
直接引用了两位原作者的大量代码,只是作了少量的修改。我没有重复造轮子,在此对原作者表示感谢。
#--------第一部分下载重要新闻---------------
import requests
from lxml import etree
def search_article(url):
"""
请求所传的url
args:
url: 所要请求的url
return:
类lxml.etree._Element的元素, 可以直接用xpath解析
"""
header = {
'Accept': '*/*',
'User - Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/66.0.3359.181 Safari/537.36'
}
resp = requests.get(url, headers=header)
html_str = str(resp.content, 'utf-8')
selector = etree.HTML(html_str)
return selector
def parse_html(selector):
"""
解析提取的lxml.etree._Element的元素
return:
type:dict
key:news title
value: contents of news
"""
try:
title_text = selector.xpath('//h1/text()')[0]
# 获取class=article的div下面的p标签的所有text()
article_text = selector.xpath('//div[@class="article"]/p//text()')
return {title_text: article_text}
except Exception as e:
return {'解析错误': [e]}
def write_article(article):
"""
将所传的新闻字典写入文件news.txt中
args:
article:dict {news_title:[contents,]}
No return
"""
file_name = 'news.txt'
f = open(file_name, 'a', encoding='utf-8')
title = list(article.keys())[0]
f.write("《"+title + "》"+'\n')
#f.write(title + '\n')
for content in article[title]:
f.write(content+"\n")
f.write("\n\n")
f.close()
def extract_url(url):
href_lists = search_article(url).xpath("//div[@id='syncad_1']//a//@href")
return href_lists
if __name__ == '__main__':
url = "http://news.sina.com.cn/"
href_list = extract_url(url=url)
file_name = 'news.txt'
#清空文件
f = open(file_name, 'w', encoding='utf-8')
f.truncate()
f.close()
for href in href_list:
# 排除非新浪连接
if href.startswith("http://news.sina.com.cn/"):
try:
html = search_article(href)
article = parse_html(html)
write_article(article)
except Exception as e:
print(e)
####--------第二部份,生成词云---------------------------------------------
import jieba #jieba分词
import matplotlib.pyplot as plt#绘制图形
from scipy.misc import imread#处理图像
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator#词云
#一.文本获取,利用jieba分词获取文本中的词
file=open('news.txt',encoding='UTF-8').read()
word=' '.join(jieba.cut_for_search(file))
#二.词云背景图像获取
image=imread('test.jpg') # 解析该图片
#三.词云设置
wc=WordCloud(
mode='RGBA',#设置透明底色
background_color='white',
mask=image, #词云形状设置为背景图像
max_words=200,#显示的词的最大个数
font_path="C:\\Windows\\Fonts\\STFANGSO.ttf",#设置字体,否则中文可能会出现乱码
scale=3#扩大三倍
)
#生成词云
image_colors = ImageColorGenerator(image)# 基于背景颜色设置字体色彩
wc.generate(word)#根据文本生成词云
#显示
plt.imshow(wc)#显示词云图
plt.axis("off")#关闭坐标轴
plt.show()#显示窗口
wc.to_file('test.png')# 保存图片