网络爬虫爬取新闻报道高频词汇

选题背景:

社会:新闻可以让我们第一时间了解到一些新发行的法律法规;可以让我们多了解社会上的风气与文化;可以让我们多知道一些名人事迹以及政治经济发展状况。新闻事实是客观的,它能满足传播主体和接受主体新闻需求的性能,也是一种不以主观意志为转移的客观存在。

经济:新闻可以让我们预见未来的一些趋势,根据关键词可以了解到未来生活发展中,兴起的产业或技术。古人云,知己知彼百战百胜。机遇是留给有准备的人的,要想把握机遇,信息的获取就是必要的。

预期目标:获取指定时间内的新闻时间,爬取新闻中的所有词汇,并按照词语的出现次数排序,并统计出现次数。

数据来源:中国新闻网

 

 

设计方法:

内容与数据特征分析:要获取的是该网站首页链接内新闻中的词汇,这些词汇都是text形式,且长度一般不超过十个字符。

方案概述:要获取的是该网站首页链接内新闻中的词汇,所以要用正则表达式匹配出我们想要获取的网址链接的共同点,该网站设置了字母和数字混编的随机码,在这个步骤卡了一小点时间。然后爬取新闻正文中的全部词汇,

主题页面的结构特征分析:

该网站采用‘utf-8’编码格式,首页由table中包含a标签加上跳转链接与图片组成。

网络爬虫程序设计:

获取网页:

 1 import requests
 2 from bs4 import BeautifulSoup
 3 import re
 4 url = 'http://www.chinadaily.com.cn/'
 5 def getUrlData(url):
 6     try:
 7         r = requests.get(url,timeout=30)
 8         r.raise_for_status
 9         r.encoding=r.apparent_encoding
10         html = r.text
11         return html
12     except:
13         return '发生异常'
14 #获取网页数据
15 wbdata = requests.get(url).text
16 #使用html解析器
17 soup=BeautifulSoup(wbdata,"html.parser")
18 print (soup)

 

取出两个网址,使用正则表达式完善规则,使代码能自动提取出符合规则的网址,即我们需要的网页:

#取出两个网址
linklist = ['www.chinadaily.com.cn/a/202106/14/WS60c68a81a31024ad0bac68e2.html','www.chinadaily.com.cn/a/202106/14/WS60c6916da31024ad0bac68f4.html','javascript:void(0)']
#用逗号将网址隔开
s = ",".join(linklist)
print(s)
#用正则表达式和网址共同部分匹配王者
#[a-z0-9A-Z]*为正则表达式匹配0个或多个数字和字母组合的字符串
links = re.findall('www.chinadaily.com.cn/a/202106/14/WS60[a-z0-9A-Z]*\.html', s)
#输出结果,查看网址匹配效果
print(links)

 

使用正则表达式,对获取爬取到的网页中的所有网址进行循环匹配:

linklist = []
for k in soup.find_all('a'):
    link = k.get('href')
    linklist.append(link)
    set(linklist)#去重
s = ",".join(linklist)
#print(linklist)
#[a-z0-9A-Z]*为正则表达式匹配0个或多个数字和字母组合的字符串
links = re.findall('www.chinadaily.com.cn/a/202106/14/WS60[a-z0-9A-Z]*\.html', s)
print(len(links))
#print(links)
#创建一个空list
newlist = []
#使用循环将整合的link数据集下标赋予新list
for i in linklist:
    link = re.findall('www.chinadaily.com.cn/a/202106/14/WS60[a-z0-9A-Z]*\.html', i)
    if link != []:
            newlist.append(link[0])
#循环给links中每个网址补齐
for i in range(0,len(links)):
    newlist[i] = 'http://' + links[i]
#输出完整网址的列表
print(newlist)

 

将获取到的网址通过循环写入新的列表,并打开网址,将网页内的所有词汇写入词典,并将不需要的东西替换掉,将所有字母转为小写方便统计:

for url in newlist:
    print(url)
    wbdata = requests.get(url).content
    soup = BeautifulSoup(wbdata,'lxml')
    # 替换换行字符
    text = str(soup).replace('\n','').replace('\r','')
    # 替换<script>标签
    text = re.sub(r'\<script.*?\>.*?\</script\>',' ',text)
    # 替换HTML标签
    text = re.sub(r'\<.*?\>'," ",text)
    text = re.sub(r'[^a-zA-Z]',' ',text)
    # 转换为小写
    text = text.lower()
    text = text.split()
    text = [i for i in text if len(i) > 1 and i != 'chinadaily' and i != 'com' and i != 'cn']
    text = ' '.join(text)
    print (text)
    with open(r"D:\新建文件夹\1.txt",'a+') as file:
        file.write(text+' ')
        print("写入成功")

 

统计txt文档中出所有词汇的出现次数,并记录排序。显示词汇总数,并显示前50个。

 

 

from nltk.corpus import stopwords
from nltk.probability import *
from nltk.corpus import PlaintextCorpusReader
import nltk

corpus_root = 'D:\新建文件夹'
#载入文件作为语料库
wordlists = PlaintextCorpusReader(corpus_root, '.*') 
 #获取整个语料库中的词汇
text = nltk.Text(wordlists.words('1.txt')) 
print (len(text))
fdist = FreqDist(text)
print (fdist) 
#设置以字典值排序,使频率从高到低显示
newd = sorted(fdist.items(), key=lambda fdist: fdist[1], reverse=True)     
#输出频率最高的前50个词汇及出现次数
print (newd[:50])

 

将文件转为csv格式,为了方便后续的画图:

#将list列表通过DataFrame转换为csv格式
import pandas as pd
#将list分为两列,加上列名
name=['热频词汇','出现次数']
test=pd.DataFrame(columns=name,data=newd)
print(test)
test.to_csv('D:/testcsv.csv',encoding='gbk')

 

取出出现次数最多的前十个词汇及次数:

import csv
from pyecharts import options as opts
from pyecharts.charts import Bar

#读取表
data_df = pd.read_csv('D:/testcsv.csv',encoding='utf-8')
df = data_df.dropna()
df1 = df[['热频词汇', '出现次数']]
data_df.sort_values(by='出现次数',ascending=False)
#取前10最高频词
df2 = df1.iloc[:10]
print(df2['热频词汇'].values)
print(df2['出现次数'].values)

 

绘制柱状图:

from pyecharts.charts import Line        # 导入图表类
from pyecharts.faker import Faker        # 用来造假数据的,示例用
from pyecharts import options as opts    # 导入配置方法
from pyecharts.globals import ThemeType  # 导入主题样式,对我这个色弱太友好了
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.INFOGRAPHIC ))
#x轴数据
bar.add_xaxis(list(df2['热频词汇'].values)) 
#y轴数据
bar.add_yaxis("词汇出现次数",cishu)
#设置标签配置项
bar.set_series_opts(label_opts=opts.LabelOpts(position="top"))
#设置标题
bar.set_global_opts(title_opts=opts.TitleOpts(title="高频词前10统计表"))
#直接在notebook显示图表
bar.render_notebook()

 

扩大汇图范围:

df3 = df1.iloc[:20]
print(df3)

  

from pyecharts.charts import Line        # 导入图表类
from pyecharts.faker import Faker        # 用来造假数据的,示例用
from pyecharts import options as opts    # 导入配置方法
from pyecharts.globals import ThemeType  # 导入主题样式,对我这个色弱太友好了
bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.ESSOS ))
#x轴数据
bar.add_xaxis(list(df3['热频词汇'].values)) 
#y轴数据
bar.add_yaxis("词汇出现次数",cishu2)
#设置标签配置项
bar.set_series_opts(label_opts=opts.LabelOpts(position="top"))
#设置标题
bar.set_global_opts(title_opts=opts.TitleOpts(title="高频词前20统计表"))
#直接在notebook显示图表
bar.render_notebook()

 

 绘制散点图

import matplotlib.pyplot as plt
plt.xlabel("词语")
plt.scatter(list(df2['热频词汇'].values), cishu, color='b', s=100, marker="o")
plt.xlabel("词语")
plt.ylabel("出现次数")
plt.title("词语出现频率(越上方出现次数越低)")
plt.grid() # 添加网格
plt.show()

 

完整代码:

  1 import requests
  2 from bs4 import BeautifulSoup
  3 import re
  4 url = 'http://www.chinadaily.com.cn/'
  5 def getUrlData(url):
  6     try:
  7         r = requests.get(url,timeout=30)
  8         r.raise_for_status
  9         r.encoding=r.apparent_encoding
 10         html = r.text
 11         return html
 12     except:
 13         return '发生异常'
 14 #获取网页数据
 15 wbdata = requests.get(url).text
 16 #使用html解析器
 17 soup=BeautifulSoup(wbdata,"html.parser")
 18 print (soup)
 19 #取出两个网址
 20 linklist = ['www.chinadaily.com.cn/a/202106/14/WS60c68a81a31024ad0bac68e2.html','www.chinadaily.com.cn/a/202106/14/WS60c6916da31024ad0bac68f4.html','javascript:void(0)']
 21 #用逗号将网址隔开
 22 s = ",".join(linklist)
 23 print(s)
 24 #用正则表达式和网址共同部分匹配王者
 25 #[a-z0-9A-Z]*为正则表达式匹配0个或多个数字和字母组合的字符串
 26 links = re.findall('www.chinadaily.com.cn/a/202106/14/WS60[a-z0-9A-Z]*\.html', s)
 27 #输出结果,查看网址匹配效果
 28 print(links)
 29 linklist = []
 30 for k in soup.find_all('a'):
 31     link = k.get('href')
 32     linklist.append(link)
 33     set(linklist)#去重
 34 s = ",".join(linklist)
 35 #print(linklist)
 36 #[a-z0-9A-Z]*为正则表达式匹配0个或多个数字和字母组合的字符串
 37 links = re.findall('www.chinadaily.com.cn/a/202106/14/WS60[a-z0-9A-Z]*\.html', s)
 38 print(len(links))
 39 #print(links)
 40 #创建一个空list
 41 newlist = []
 42 #使用循环将整合的link数据集下标赋予新list
 43 for i in linklist:
 44     link = re.findall('www.chinadaily.com.cn/a/202106/14/WS60[a-z0-9A-Z]*\.html', i)
 45     if link != []:
 46             newlist.append(link[0])
 47 #循环给links中每个网址补齐
 48 for i in range(0,len(links)):
 49     newlist[i] = 'http://' + links[i]
 50 #输出完整网址的列表
 51 print(newlist)
 52 for url in newlist:
 53     print(url)
 54     wbdata = requests.get(url).content
 55     soup = BeautifulSoup(wbdata,'lxml')
 56     # 替换换行字符
 57     text = str(soup).replace('\n','').replace('\r','')
 58     # 替换<script>标签
 59     text = re.sub(r'\<script.*?\>.*?\</script\>',' ',text)
 60     # 替换HTML标签
 61     text = re.sub(r'\<.*?\>'," ",text)
 62     text = re.sub(r'[^a-zA-Z]',' ',text)
 63     # 转换为小写
 64     text = text.lower()
 65     text = text.split()
 66     text = [i for i in text if len(i) > 1 and i != 'chinadaily' and i != 'com' and i != 'cn']
 67     text = ' '.join(text)
 68     print (text)
 69     with open(r"D:\新建文件夹\1.txt",'a+') as file:
 70         file.write(text+' ')
 71         print("写入成功")
 72 from nltk.corpus import stopwords
 73 from nltk.probability import *
 74 from nltk.corpus import PlaintextCorpusReader
 75 import nltk
 76 
 77 corpus_root = 'D:\新建文件夹'
 78 #载入文件作为语料库
 79 wordlists = PlaintextCorpusReader(corpus_root, '.*') 
 80  #获取整个语料库中的词汇
 81 text = nltk.Text(wordlists.words('1.txt')) 
 82 print (len(text))
 83 fdist = FreqDist(text)
 84 print (fdist) 
 85 #设置以字典值排序,使频率从高到低显示
 86 newd = sorted(fdist.items(), key=lambda fdist: fdist[1], reverse=True)     
 87 #输出频率最高的前50个词汇及出现次数
 88 print (newd[:50])
 89 #将list列表通过DataFrame转换为csv格式
 90 import pandas as pd
 91 #将list分为两列,加上列名
 92 name=['热频词汇','出现次数']
 93 test=pd.DataFrame(columns=name,data=newd)
 94 print(test)
 95 test.to_csv('D:/testcsv.csv',encoding='gbk')
 96 import csv
 97 from pyecharts import options as opts
 98 from pyecharts.charts import Bar
 99 
100 #读取表
101 data_df = pd.read_csv('D:/testcsv.csv',encoding='utf-8')
102 df = data_df.dropna()
103 df1 = df[['热频词汇', '出现次数']]
104 data_df.sort_values(by='出现次数',ascending=False)
105 #取前10最高频词
106 df2 = df1.iloc[:10]
107 print(df2['热频词汇'].values)
108 print(df2['出现次数'].values)
109 import numpy as np #导入numpy计算模块
110 import matplotlib.pyplot as plt #导入matplotlib.pyplot画图模块
111 plt.rcParams['font.sans-serif']='SimHei' #设置中文显示
112 plt.rcParams['axes.unicode_minus']=False
113 data=pd.read_csv('D:/testcsv.csv',encoding='utf-8')
114 #提取其中的'热频词汇'数组,视为数据的标签
115 name=data['热频词汇']
116 #提取'出现次数'数组:数据存在位置
117 values=data['出现次数']
118 print(values[:10])
119 print(name[:10])
120 from pyecharts.charts import Line        # 导入图表类
121 from pyecharts.faker import Faker        # 用来造假数据的,示例用
122 from pyecharts import options as opts    # 导入配置方法
123 from pyecharts.globals import ThemeType  # 导入主题样式,对我这个色弱太友好了
124 bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.INFOGRAPHIC ))
125 #x轴数据
126 bar.add_xaxis(list(df2['热频词汇'].values)) 
127 #y轴数据
128 bar.add_yaxis("词汇出现次数",cishu)
129 #设置标签配置项
130 bar.set_series_opts(label_opts=opts.LabelOpts(position="top"))
131 #设置标题
132 bar.set_global_opts(title_opts=opts.TitleOpts(title="高频词前10统计表"))
133 #直接在notebook显示图表
134 bar.render_notebook()
135 #扩大范围:
136 df3 = df1.iloc[:20]
137 print(df3)
138 from pyecharts.charts import Line        # 导入图表类
139 from pyecharts.faker import Faker        # 用来造假数据的,示例用
140 from pyecharts import options as opts    # 导入配置方法
141 from pyecharts.globals import ThemeType  # 导入主题样式,对我这个色弱太友好了
142 bar = Bar(init_opts=opts.InitOpts(theme=ThemeType.ESSOS ))
143 #x轴数据
144 bar.add_xaxis(list(df3['热频词汇'].values)) 
145 #y轴数据
146 bar.add_yaxis("词汇出现次数",cishu2)
147 #设置标签配置项
148 bar.set_series_opts(label_opts=opts.LabelOpts(position="top"))
149 #设置标题
150 bar.set_global_opts(title_opts=opts.TitleOpts(title="高频词前20统计表"))
151 #直接在notebook显示图表
152 bar.render_notebook()
153 import matplotlib.pyplot as plt
154 plt.xlabel("词语")
155 plt.scatter(list(df2['热频词汇'].values), cishu, color='b', s=100, marker="o")
156 plt.xlabel("词语")
157 plt.ylabel("出现次数")
158 plt.title("词语出现频率(越上方出现次数越低)")
159 plt.grid() # 添加网格
160 plt.show()

总结:

中国新闻中出现的高频词汇还是与我们生活相关的居多,毕竟是中国新闻。距离预期还是有点差距,一些常用的介词影响了数据的准确性。在此次的项目学习中,了解了正则表达式的匹配规则,并对其进行了运用。应该可以通过某些方法排除词典中常用介词,使其从中剔除,不影响最后的数据。因本人技术有限,今后学习生活中一定多多学习。

 

posted @ 2021-06-15 21:36  ctow  阅读(883)  评论(0编辑  收藏  举报