一、摘要
《解忧杂货店》原作名《 ナミヤ雑貨店の奇蹟》,是日本作家东野圭吾写作的长篇小说。2011年于《小说野性时代》连载,于2012年3月由角川书店出版,2014年5月,南海出版公司出版中文版,译者李盈春。该书讲述了在僻静街道旁的一家杂货店,只要写下烦恼投进店前门卷帘门的投信口,第二天就会在店后的牛奶箱里得到回答:因男友身患绝症,年轻女孩月兔在爱情与梦想间徘徊;松冈克郎为了音乐梦想离家漂泊,却在现实中寸步难行;少年浩介面临家庭巨变,挣扎在亲情与未来的迷茫中……他们将困惑写成信投进杂货店,奇妙的事情随即不断发生。同名华语电影于2017年上映。 2017年12月15日,亚马逊中国发布基于亚马逊阅读大数据产生的一系列年度阅读榜单。其中,东野圭吾的《解忧杂货店》连续4年上榜,又一次成为2017年亚马逊最畅销图书。
本人非常喜欢这部小说,在学Python过程中,使用requests+BeautifulSoup爬取了豆瓣网上该书书评,并通过借鉴如何用Python做舆情时间序列可视化?,基于用户评论的短文本情感分析模型设计两篇文章的思路,对书评进行了情感分析。
二、开发环境
版本:python3.5.2
编程软件:pycharm
配置库:
- pip install pyecharts
- pip install BeautifulSoup
- pip install requests
- pip install pymongo
- pip install snownlp
- pip install Pandas
三、爬虫设计与实现
爬虫思路很线性,获取网页链接,通过get_page()函数获取网页,返回页面信息,通过parse_one_page()函数进行解析获取信息,通过save_to_mongo()函数将数据存储至MongoDB数据库中。具体代码如下:
def get_page(url_base):
print('正在读取页面……')
ips = ['自己爬一些可用ip']
proxy_ip = {'http':ips[random.randint(0, 9) ]}
try:
response = requests.get(url_base,proxies = proxy_ip)
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
def parse_one_page(html1):
soup = BeautifulSoup(html1, "html.parser")
for item in soup.find_all(class_="comment-item"):
comment_info = {
'user_name': None,
'user_url': None,
# 'user_loc': None,
'star': None,
'time': None,
'useful': None,
'comment': None
}
try:
comment_info['user_name'] = item.find(class_ ='avatar').find('a').get('title')
except:
pass
try:
comment_info['user_url'] = item.find(class_ ='avatar').find('a').get('href')
except:
pass
try:
tmp = item.find(class_="comment-info").find('span').get('title')
if tmp == '力荐':
comment_info['star'] = 5
elif tmp == '推荐':
comment_info['star'] = 4
elif tmp == '还行':
comment_info['star'] = 3
elif tmp == '较差':
comment_info['star'] = 2
elif tmp == '很差':
comment_info['star'] = 1
except:
pass
try:
if comment_info['star']==None:
comment_info['time'] = item.find(class_="comment-info").find_all('span')[0].get_text().split('-')
else:
comment_info['time'] = item.find(class_="comment-info").find_all('span')[1].get_text().split('-')
except:
pass
try:
comment_info['useful'] = int(item.find(class_="vote-count").get_text())
except:
pass
try:
comment_info['comment'] = item.find(class_="short").get_text()
except:
pass
save_to_mongo(comment_info)
def save_to_mongo(result):
try:
if db[MONGO_TABLE].insert(result):
print('存储到MongoDB成功',result)
except Exception:
print('存储到MongoDB失败', result)
def main():
url_base = 'https://book.douban.com/subject/25862578/comments/hot?'
html = get_page(url_base)
page_num = int(get_page_num(html))
print(math.ceil(page_num / 20))
for i in range(1,math.ceil(page_num/20)):
url_tmp = url_base + "p=%s"%i
html1 = get_page(url_tmp)
time.sleep(4)
try:
parse_one_page(html1)
print(i, '页正常')
except:
print(i,'页出错')
对于网页翻页,由于网页链接特点为 url_base = 'https://book.douban.com/subject/25862578/comments/hot?'shizip=num,多以获取总条数后除以每页评论量,得到总页数,进行循环。如图:
def get_page_num(html):
soup = BeautifulSoup(html, "html.parser")
page_num = soup.find(id='total-comments').get_text().replace("全部共 ","").replace(" 条","")
print(page_num)
return page_num
在实际运行过程中出现了被反爬虫的情况,403:
解决方案python爬虫防止IP被封的一些措施。主要采用:
1.构建代理池,每次发出请求,伪装一个ip,避免同一ip多次使用。https://github.com/Germey/ProxyPool使用Redis+Flask维护动态代理池,使用该项目爬取了一些免费网站上的ip,由于免费,可用的不多,凑合用(手动狗头)
response = requests.get(url_base,proxies = proxy_ip)
2.延长请求之间的时间,减小访问评率,也是笨办法。
最终获取数据如图:
爬取数据.PNG
四、SnowNLP书评情感分析
SnowNLP是基于中文文本的文本情感分析包,其训练数据就是评论数据,但是和书评差异还是很大的,此次只是尝试,比较浅显。从数据库中提取评论数输入模型中,得到评分结果。文章如何用Python做情感分析?有详细解释。
from snownlp import SnowNLP
def get_sentiment_cn(text):
s = SnowNLP(text)
return s.sentiments
模型输出结果与用户评星(1-5归一化)结果进行比较,截取了23组进行展示:
从结果看,大部分结果还是能反应用户评分的,也有不少错的比较离谱,这是因为训练数据与本文数据不是同一类型,要提高效率还得用此类数据进行训练(下次再做)。拿出具体数据看一下:
评分表.PNG
第14、22行评星很高但是模型给出的确实相反的结论,因为类似“泪目”“免疫”“”“睡着了”在snownlp 模型中属于比较消极的词汇,而评论的人要表达的意思却相反。第3、21条都是倾向很明显的词,所以结果正确,第24行是一个中性的评论,但由于“变态”的出现,模型判定为消极情感。
总而言之,此次试验能大概反应感情的倾向,但是离精确还差的很远。可以参考如何用Python和机器学习训练中文文本情感分类模型?
五、其他数据分析
选取了20000余组数据进行分析。
1.历年读者评论量
年度评价数量 (1).png
2.用户评价情况
读者打分.png
读者打分比例 (1).png
关注“1024程序开发者社区”,回复“解忧杂货店”,获取代码和更多资源!
关注我.jpg
网友评论