最近网易研发出一款末日生存题材的手游——《明日之后》,我本人对这种类型的游戏很感兴趣,但是又担心网易第一次做这种类型的游戏没有经验,所以我准备使用Python爬虫,来爬取百度贴吧关于明日之后手游的帖子,来具体分析一下明日之后这款手游。具体思路就是使用Python爬虫获取百度贴吧有关明日之后的帖子的标题,然后把他们爬取到一个txt文本,之后再利用Python的matplotlib和jieba等第三方库来生成一个关键字词云,通过观察词云来初步评测一下明日之后,然后,我在利用Python的第三方库snownlp来进行情感分析,看一下贴吧中对明日之后的评价是正向的还是负向的。
注意:
以上所提到到第三方库安装方式有两种,一种是在安装Python的文件夹下,使用cmd命令行工具,利用pip install 库文件,在线安装;另一种方式是去指定的库文件的官方网站下载安装包,然后把安装包放在Python的安装文件夹下,同样要打开cmd命令行,使用pip install 安装包名,进行安装。使用第一种安装方式的时候,有的时候会提示安装失败(失败的原因可能是版本不对,或者安装包在线找不到),这个时候需要使用第二种安装方式来安装,使用第二种安装方式的时候,需要注意下载的安装包要与Python的版本一致。
Scrapy Engine(Scrapy 核心) 负责数据流在各个组件之间的流。Spiders(爬虫) 发出 Requests 请求,经由 Scrapy Engine(Scrapy 核心) 交给 Scheduler(调度器),Downloader(下载器)Scheduler(调度器) 获得 Requests 请求,然后根据 Requests 请求,从网络下载数据。Downloader(下载器) 的 Responses 响应再传递给 Spiders 进行分析。根据需求提取出 Items,交给 Item Pipeline 进行下载。所以我们需要设置四个Python文件,分别是settings.py、pipelines.py、items.py、以及爬虫文件。
在爬取贴吧之前,我们先要分析一下贴吧的页面结构,通过明日之后贴吧首页,进入贴吧首页,然后右击审查元素,可以查看页面结构,类似这样:
左边被选中的标题,所对应的在右边的标签中。
在scrapy框架中,还有一个强大的功能,通过命令行的shell命令可以辅助分析页面结构,在scrapy下有两种方式访问网页指定元素的方式,一种是通过xpath的方式,另一种是通过css选择器。
首先,在python文件夹下,用cmd命令行scrapy shell 明日之后的url:然后会进入可便捷状态,类似这样:
这个时候可以用response命令查看页面的全部信息,比如使用response.body可以查看页面body标签的元素:
在提取页面元素方面,xpath和css选择器各有优点,对于处理复杂页面元素,css选择器变现更好一点,所以我在这里选择使用css选择器。我通过审查元素看到在贴吧的题目是在class为threadlist_title.pull_left.j_th_tit的div标签下,所以在shell命令行输入:response.css("#thread_list div.threadlist_title.pull_left.j_th_tit a::text").extract()这个命令,可以查看当前页面所有帖子的标题:
获取到了目标元素,就可以进行爬取工作了。
在cmd命令行使用:scrapy startproject tieba来生成一个scrapy结构文件夹,目录是这个样子的:
tieba/
scrapy.cfg
tieba/
__init__.py
items.py
middlewares.py
pipelines.py
settings.py
spiders/
__init__.py
class TiebaspiderSpider(scrapy.Spider):
name = 'tiebaspider'
# allowed_domains = ['https://tieba.baidu.com/']
# start_urls = ['https://tieba.baidu.com/f?kw=明日之后&ie=utf-8&pn=0']
# start_urls =['http://169tp.com/']
url = 'https://tieba.baidu.com/f?kw=明日之后&ie=utf-8&pn='
offset = 0
# 起始url
start_urls = [url + str(offset)]
# re_rule = re.compile('def parse(self, response):
print("开始爬虫:")
div_list = response.css("#thread_list div.threadlist_title.pull_left.j_th_tit a::text").extract()
# div_list = response.xpath('//u[@id = "thread_list"]//div[@class = "threadlist_title.pull_left.j_th_tit"]//a/text()').extract()
# div_url = re.findall(self.re_rule, div_list)
# print(div_list
item = TiebaItem()
item['text'] = div_list
yield item
if self.offset < 500:
self.offset += 50
# print("结束爬虫")
yield scrapy.Request(self.url + str(self.offset), callback = self.parse)
分析:
start_url是最开始的url,开始爬虫之后会进入parse函数,在parse函数中,通过css选择器获取页面的元素,然后通过yield来进行后续的爬虫,yield item是把爬虫的元素传送到pipelines文件处理,yield scrapy. Request是指定下一次爬取的url。
打开items.py文件,在这里是处理页面元素的格式核心就是生命数据的对象格式:
text = scrapy.Field()
ITEM_PIPELINES = {
'tieba.pipelines.TiebaPipeline': 300,
}
class TiebaPipeline(object):
def __init__(self):
self.filename = open("test.txt", "a", encoding="utf-8")
def process_item(self, item, spider):
res=dict(item)
for i in range(0, 20) :
com = res['text'][i]
# print(com)
self.filename.write(com+'\n')
print('完成当前页面。。。')
# self.file.write(line.encode('utf-8')+'\n')
def close_spider(self, spider):
self.filename.close()
主要是打开文件,写入文件,关闭文件,
这里有一个问题,就是乱码问题,在写入文件的时候,必须指定写入文件的编码方式utf-8,不指定编码的话,写入的文件会出现乱码。
爬虫爬取数据存储在指定路径下,之后就可以生成词云,生成的词云有两种表现方式,一种是正正方方的词云,一种以某个图片为背景的词云。
生成的词云可以进行多种个性化的设定,根据wordcloud库的源码:
可以设定比如长宽,词云的最多单词数量,背景,字体大小,字体格式,颜色,等等属性,这里一切从简,能默认的全部默认,
核心代码:
def GetWordCloud():
path_txt = 'C://D/Python/scrapyDemo/tieba/test.txt'
path_img = "C://D/Python/PythonDemo/2.png"#
f = open(path_txt, 'r', encoding='UTF-8').read()
background_image = np.array(Image.open(path_img))
# 结巴分词,生成字符串,如果不通过分词,无法直接生成正确的中文词云,感兴趣的朋友可以去查一下,有多种分词模式
#Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
cut_text = " ".join(jieba.cut(f))
wordcloud = WordCloud(
# 设置字体,不然会出现口字乱码,文字的路径是电脑的字体一般路径,可以换成别的
font_path="C:/Windows/Fonts/simfang.ttf",
background_color="black",
# mask参数=图片背景,必须要写上,另外有mask参数再设定宽高是无效的
mask=background_image).generate(cut_text)
# 生成颜色值
image_colors = ImageColorGenerator(background_image)
# 下面代码表示显示图片
plt.imshow(wordcloud.recolor(color_func=image_colors), interpolation="bilinear")
plt.axis("off")
plt.show()
大体流程就是:
绘制完成词云之后,我们在此读入文本,来绘制情感趋势折线图。在这里使用的是snownlp,SnowNLP 是国人开发的 python 类库,可以方便的处理中文文本内容,是受到了 TextBlob 的启发而写的,由于现在大部分的自然语言处理库基本都是针对英文的,于是写了一个方便处理中文的类库,并且和 TextBlob 不同的是,这里没有用 NLTK,所有的算法都是自己实现的,并且自带了一些训练好的字典。
注意本程序都是处理的 unicode 编码,所以使用时请自行 decode 成 unicode。
核心代码如下:
txt = open('C://D/Python/scrapyDemo/tieba/test.txt','r', encoding='UTF-8')
text = txt.readlines()
n = 0#获取文本行数
for num in text :
n = n +1
txt.close()
print('读入成功', '共读入'+str(n)+'行')
sentences = []
senti_score = []
for i in text:
a1 = SnowNLP(i)
a2 = a1.sentiments
sentences.append(i) # 语序...
senti_score.append(a2)
print('doing')
table = pd.DataFrame(sentences, senti_score)
# table.to_excel('F:/_analyse_Emotion.xlsx', sheet_name='Sheet1')
# ts = pd.Series(sentences, senti_score)
# ts = ts.cumsum()
# print(table)
x = []
for i in range(1, n+1) :
x.append(i)
pl.mpl.rcParams['font.sans-serif'] = ['SimHei']
pl.plot(x, senti_score)
pl.title(u'明日之后')
pl.xlabel(u'评 论 用 户')
pl.ylabel(u'情 感 程 度')
pl.show()
分析:
得到文本文件,获取文本行数作为文件的横坐标,纵坐标从0-1,0代表最差,1代表最好,使用训练好的语料库分析文本,得到每一行的喜好程度,绘制折线图。
说完效果,再说说本次设计的不足之处,在进行情感分析的时候,选择的snownlp的库文件,使用的分词和语料库是已经训练好的,但是这个库设计之初是用来分析评论的,贴吧的内容还是跟评论有一些差别,如果想要达到更好的效果,应该自己单独训练,这样的效果会更好,同时情感分析的是折线图,x轴会显示出每一个数据的感情趋向,当数据量足够大的时候,显示会有问题。