PYTHON爬虫大作业:豆瓣读书“小说”标签下1000本书籍的爬取与分析
PYTHON爬虫大作业:豆瓣读书“小说”标签下1000本书籍的爬取与分析
本文记录笔者大二下学期选修课数据科学导论的期末大作业,新手小白,才疏学浅,欢迎批评指正。
项目概述
本项目框架如下:
- 数据爬取
- 数据分析与可视化
- 项目报告
数据爬取
import requests
import re
from bs4 import BeautifulSoup
import pymysql.cursors
#给出url,爬取页面信息
def getHTMLText(url, kv):
try:
r = requests.get(url, timeout = 30, headers = kv)
r.raise_for_status()
#r.encoding = r.apparent_encoding #该语句导致标签显示为乱码
r.encoding = 'utf-8'
return r.text
except:
print('爬取失败')
#建立表格
def buildTable():
conn = pymysql.connect(
host = '127.0.0.1',
user = 'root',
passwd = 'sime1234', #数据库密码
db = 'douban_novels',
charset = 'utf8mb4'
)
cursor = conn.cursor()
sql_create1 = '''CREATE TABLE NOVELS(
NO INT PRIMARY KEY,
TITLE VARCHAR(45),
AUTHOR VARCHAR(45),
RATING DECIMAL(2,1),
PUBLISHER VARCHAR(45))
'''
cursor.execute(sql_create1)
print('BOOKS CREATED')
sql_create2 = '''CREATE TABLE NOVEL_TAGS(
BOOKNO INT,
TAG VARCHAR(45))
'''
cursor.execute(sql_create2)
print('TAGS CREATED')
cursor.close()
conn.close()
#给出书籍编号、链接与标题,爬取书籍详情信息,形成字典并返回
def getBookInfo(no, href, title):
kv = {
#略。提示:将头文件的头部信息复制过来,加上引号和逗号形成字典,注意要删掉Accept-Encoding一行。
}
html = getHTMLText(href, kv)
book = BeautifulSoup(html, 'html.parser')
bookInfo = {'author' : '未知',
'rating' : 0.0,
'publisher' : '未知'}
bookInfo['no'] = no
bookInfo['title'] = title
rating = book.find('strong')
if rating.string:
try:
bookInfo['rating'] = float(rating.text)
except:
pass
for keyTag in book.find_all(name = 'span', attrs = {'class' : 'pl'}):
if re.search(r'作者', str(keyTag.string)):
author = keyTag#.parent
for i in range(4):
author = author.next_element
author = author.replace('\n', '')
author = author.replace(' ', '')
bookInfo['author'] = author
for keyTag in book.find_all(string = '出版社:'):
publisher = keyTag.parent
for i in range(2):
publisher = publisher.next_element
publisher = publisher.replace('\n', '')
publisher = publisher.replace(' ', '')
bookInfo['publisher'] = publisher
tags = []
for tag in book.find_all(attrs = {'class' : 'tag'}):
tags.append(tag.text)
print(tags)
bookInfo['tags'] = tags
print(bookInfo)
return bookInfo
#爬取豆瓣读书小说标签下综合排序前1000本小说的信息
def getBooks():
conn = pymysql.connect(
host = '127.0.0.1',
user = 'root',
passwd = 'sime1234', #数据库密码
db = 'douban_novels',
charset = 'utf8mb4'
)
cursor = conn.cursor()
no = 0
start_url = "https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4?start="
kv = {
#略。提示:将头文件的头部信息复制过来,加上引号和逗号形成字典,注意要删掉Accept-Encoding一行。
}
for i in range(50):
print('第{0}页'.format(i + 1))
end_url = str(20 * i)
html = getHTMLText(start_url + end_url, kv)
topBooks = BeautifulSoup(html, 'html.parser')
for book in topBooks.find_all('a'):
href = str(book['href'])
if re.match(r'https://book.douban.com/subject/', href):
title = book.get('title')
if title:
no += 1
info = getBookInfo(no, href, title)
sql_insert1 = "INSERT INTO NOVELS(NO, TITLE, AUTHOR, RATING, PUBLISHER)\
VALUES({0}, '{1}', '{2}', {3}, '{4}')".format(info['no'], \
info['title'], info['author'], str(info['rating']), info['publisher'])
cursor.execute(sql_insert1)
print(('book{0} stored').format(info['no']))
tags = info['tags']
for i in range(len(tags)):
sql_insert2 = "INSERT INTO NOVEL_TAGS(BOOKNO, TAG) VALUES({0}, '{1}')".format(info['no'], tags[i])
cursor.execute(sql_insert2)
print(('book{0} tags stored').format(info['no']))
conn.commit()
cursor.close()
conn.close()
if __name__ == '__main__':
buildTable()
getBooks()
数据分析与可视化
·书籍标签词云
import pymysql.cursors
import wordcloud
from scipy.misc import imread
#以空格为间隔,将标签连接成一个string
def get_tags_str():
conn = pymysql.connect(
host = '127.0.0.1',
user = 'root',
passwd = 'sime1234', #数据库密码
db = 'douban_novels',
charset = 'utf8mb4'
)
cursor = conn.cursor()
sql_select = 'select tag from douban_novels.novel_tags'
cursor.execute(sql_select)
tags = cursor.fetchall()
tags_str = ''
for tag in tags:
tags_str += tag[0]
tags_str += ' '
cursor.close()
conn.close()
return tags_str
#以空格为间隔,将出版社连接成一个string
def get_publishers_str():
conn = pymysql.connect(
host = '127.0.0.1',
user = 'root',
passwd = 'sime1234', #数据库密码
db = 'douban_novels',
charset = 'utf8mb4'
)
cursor = conn.cursor()
sql_select = 'select publisher from douban_novels.novels'
cursor.execute(sql_select)
publishers = cursor.fetchall()
publishers_str = ''
for publisher in publishers:
publishers_str += publisher[0]
publishers_str += ' '
cursor.close()
conn.close()
return publishers_str
#生成词云
if __name__ == '__main__':
#读取卡通书本图片
mask = imread('book.png')
#生成并配置wordcloud对象
w = wordcloud.WordCloud(font_path = 'msyh.ttc', mask = mask,\
#width = 2000, height = 1000, \
background_color = 'white', max_words = 200)
#生成标签词云
tags_str = get_tags_str()
w.generate(tags_str)
w.to_file('tags_wordcloud.png')
print('tags_wordcloud.png generated')
#生成出版社词云
publishers_str = get_publishers_str()
w.generate(publishers_str)
w.to_file('publishers_wordcloud.png')
print('publishers_wordcloud.png generated')
·箱线图与直方图
import pymysql.cursors
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.family'] = 'SimHei'
plt.figure(dpi = 600)
#连接数据库
conn = pymysql.connect(
host = '127.0.0.1',
user = 'root',
passwd = 'sime1234', #数据库密码
db = 'douban_novels',
charset = 'utf8mb4'
)
cursor = conn.cursor()
#生成dataframe:图书信息与高分图书信息
sql_select = 'select * from douban_novels.novels'
cursor.execute(sql_select)
title = []
author = []
rating = []
publisher = []
for book in cursor.fetchall():
title.append(book[1])
author.append(book[2])
if book[3] == 0:
rating.append(None)
else:
rating.append(float(book[3]))
if book[4] == '未知':
publisher.append(None)
else:
publisher.append(book[4])
dic = {'TITLE' : title, 'AUTHOR' : author,\
'RATING' : rating, 'PUBLISHER' : publisher}
d = pd.DataFrame(dic) #生成dataframe:图书信息
d_high_rating = d[d['RATING'] >= 8.5] #生成dataframe:高分图书信息
#得到图书各类信息的描绘信息
print('\n' + '1000本小说评分统计信息', end = '\n')
d_des = d.describe()
d_des.to_csv('1000本小说评分统计信息.csv')
print(d_des)
print('\n' + '1000本小说作者统计信息', end = '\n')
d_aut_des = d['AUTHOR'].describe()
d_aut_des.to_csv('1000本小说作者统计信息.csv')
print(d_aut_des)
print('\n' + '1000本小说出版社统计信息', end = '\n')
d_pls_des = d['PUBLISHER'].describe()
d_pls_des.to_csv('1000本小说出版社统计信息.csv')
print(d_pls_des)
#图书评分箱线图
rating_box = d.plot.box(title="1000本小说评分箱线图")
plt.grid(linestyle="--", alpha=0.3)
plt.savefig('1000本小说评分箱线图.png')
plt.show()
#将图书信息进行分类统计,统计1000本小说中出现最多的10个出版社的出现次数
pls_group = d_high_rating.groupby('PUBLISHER')
pls_group = pls_group.size().reset_index(name='counts')
pls_group = pls_group.set_index('PUBLISHER')
pls_group = pls_group.sort_values('counts', ascending = False)
pls_group = pls_group[0 : 10]
pls_bar = pls_group.plot.bar()
plt.title('1000本小说中出现最多的10个出版社的出现次数')
plt.xlabel('出现次数')
plt.ylabel('出版社')
pls_bar.legend_.remove()
plt.savefig('1000本小说中出现最多的10个出版社的出现次数.png', bbox_inches = 'tight')
plt.show()
#将高分图书信息进行分类统计,统计1000本小说中,8.5分以上的小说出现最多的10个出版社的出现次数
pls_group = d.groupby('PUBLISHER')
pls_group = pls_group.size().reset_index(name='counts')
pls_group = pls_group.set_index('PUBLISHER')
pls_group = pls_group.sort_values('counts', ascending = False)
pls_group = pls_group[0 : 10]
pls_bar = pls_group.plot.bar()
plt.title('1000本小说中,8.5分以上的小说出现最多的10个出版社的出现次数')
plt.xlabel('出现次数')
plt.ylabel('出版社')
pls_bar.legend_.remove()
plt.savefig('1000本小说中,8.5分以上的小说出现最多的10个出版社的出现次数.png', bbox_inches = 'tight')
plt.show()
#生成datframe:图书标签与高分图书标签
sql_select = '''select * from douban_novels.novels, douban_novels.novel_tags
where douban_novels.novels.NO = douban_novels.novel_tags.BOOKNO;'''
cursor.execute(sql_select)
title = []
author = []
rating = []
publisher = []
tag = []
for book in cursor.fetchall():
title.append(book[1])
author.append(book[2])
if book[3] == 0:
rating.append(None)
else:
rating.append(float(book[3]))
if book[4] == '未知':
publisher.append(None)
else:
publisher.append(book[4])
tag.append(book[6])
dic = {'TITLE' : title, 'AUTHOR' : author,\
'RATING' : rating, 'PUBLISHER' : publisher, 'TAG' : tag}
d = pd.DataFrame(dic) #生成datframe:图书标签
d_high_rating = d[d['RATING'] >= 8.5] #生成datframe:高分图书标签
#得到图书标签的描绘信息
print('\n' + '1000本小说标签统计信息', end = '\n')
d_tags_des = d['TAG'].describe()
d_tags_des.to_csv('1000本小说标签统计信息.csv')
print(d_tags_des)
#将图书标签进行分类统计,统计1000本小说中出现最多的10个标签的出现次数
tags_group = d.groupby('TAG')
tags_group = tags_group.size().reset_index(name='counts')
tags_group = tags_group.sort_values('counts', ascending = False)
tags_group = tags_group.set_index('TAG')
tags_top10 = tags_group[0 : 10]
tags_top10_bar = tags_top10.plot.bar()
plt.title('1000本小说中出现最多的10个标签的出现次数')
plt.xlabel('出现次数')
plt.ylabel('标签')
tags_top10_bar.legend_.remove()
plt.savefig('1000本小说中出现最多的10个标签的出现次数.png', bbox_inches = 'tight')
plt.show()
#将高分图书标签进行分类统计,统计1000本小说中,8.5分以上的小说出现最多的10个标签的出现次数
tags_group = d_high_rating.groupby('TAG')
tags_group = tags_group.size().reset_index(name='counts')
tags_group = tags_group.sort_values('counts', ascending = False)
tags_group = tags_group.set_index('TAG')
tags_top10 = tags_group[0 : 10]
tags_top10_bar = tags_top10.plot.bar()
plt.title('1000本小说中,8.5分以上的小说出现最多的10个标签的出现次数')
plt.xlabel('出现次数')
plt.ylabel('标签')
tags_top10_bar.legend_.remove()
plt.savefig('1000本小说中,8.5分以上的小说出现最多的10个标签的出现次数.png', bbox_inches = 'tight')
plt.show()
cursor.close()
conn.close()
·关联分析
import pymysql.cursors
from efficient_apriori import apriori
if __name__ == '__main__':
conn = pymysql.connect(
host = '127.0.0.1',
user = 'root',
passwd = 'sime1234', #数据库密码
db = 'douban_novels',
charset = 'utf8mb4'
)
cursor = conn.cursor()
sql_select = '''select douban_novels.novels.publisher, douban_novels.novel_tags.tag
from douban_novels.novels, douban_novels.novel_tags
where douban_novels.novels.NO = douban_novels.novel_tags.BOOKNO;'''
cursor.execute(sql_select)
transactions = list(cursor.fetchall())
itemsets, rules = apriori(transactions, min_support = 0.003, min_confidence = 0.1)
print(rules)
with open('出版社与标签的关联.txt', 'w') as f:
for rule in rules:
f.write(str(rule) + '\n')
cursor.close()
conn.close()
项目报告
摘要
随着数码产品的流行,人们能获得的娱乐形式越来越多样化,影视、音乐、社交媒体等等精彩刺激的娱乐形式,无疑对人们的阅读习 惯造成了极大的冲击。此外,电子书成为了很多人阅读的首选资源,快节奏的生活也使人们的阅读偏好更加偏向于碎片化的阅读。在这个时候,国人的阅读口味究竟呈现出怎样的状态?现在在国内流行的都是什么样的书籍?书籍是我们的精神食粮,通过国人的读偏好,我们得以窥见当代人的精神世界一角,并能从中得到启示与 反思。在本项目中,笔者爬取了豆瓣读书中“小说”标签下,按照综合 排序的前 1000 本小说的信息,并对数据进行分析与可视化,对国人小说阅读偏好做初步的分析。
关键词:爬虫 阅读偏好 数据分析 数据可视化
一、数据爬取
本文选择爬取的网站为豆瓣读书,具体爬取对象为:豆瓣读书的小说标签下, 按综合排序的前 1000 本小说。
具体爬取过程如下:
- 爬取豆瓣读书的小说标签下前 50 页的内容;
- 从爬取的内容中:
(1) 遍历名称为’a’的标签,找出链接前缀为’https://book.douban.com/subject/’ 的标签;
(2) 标签的’title’属性作为书籍的标题;
(3) 对书籍详情链接进行进一步爬取; - 爬取书籍详情页面:
(1) 将上一步中得到的’title’属性作为书籍标题存入字典;
(2) 查找名称为’strong’的标签,将标签的 text 属性转化为 float 类型,作为书 籍评分存入字典;
(3) 查找名称为’span’,’class’属性为’pl’的标签,在查找结果中查找标签的 strng 属性为’作者:’的标签,选取标签后的第 4 个元素作为作者存入字 典;查找标签的 string 属性’出版社’的标签,选取标签后的第 2 个元素作 为出版社存入字典;
(4) 在爬取过程中,发现部分作者标签的 string 类型为“作者”,缺失了冒 号,于是将查找条件修改为:匹配 string 属性含有’作者’字符串的标签;
(5) 查找’class’属性为’tag’的标签,将这些标签的’text’属性存储在一个列表 中,然后将列表存入字典;
(6) 将字典存入数据库
二、数据预处理
在爬取过程中,发现部分书籍的评分或者出版社有缺失的情况,于是:
1.将评分缺失的书籍评分记为 0.0 分;
2.将出版社缺失的书籍记为’未知’;
3.在读取数据库数据并生成 data frame 时,将评分为 0.0,以及出版社为’未知’ 的项读取为 None
三、数据存储
本项目选取的存储方式为存入 mysql 数据库。
以下为数据集介绍:
数据库
数据库名称 | douban_novels |
---|---|
表格 1 | novels |
表格 2 | novel_tags |
书籍信息数据集(不含标签)
表格名称:novels
共包含 1000 条数据
字段名 | 说明 |
---|---|
NO | 书籍编号,按照网页上书籍排列顺序编号,从 1 到 1000 |
TITLE | 书籍标题 |
AUTHOR | 书籍作者 |
RATING | 书籍评分 |
PUBLISHER | 书籍出版社 |
书籍标签数据集
表格名称:novel_tags
共包含 8000 条数据
字段名 | 说明 |
---|---|
BOOKNO | 书籍编号(与 novels 表格对应) |
TAG | 书籍标签 |
四、数据分析
本项目的数据分析内容包括:
1.小说统计信息
(1)评分统计信息(生成 csv 文件)
(2)作者统计信息(生成 csv 文件)
(3)出版社统计信息(生成 csv 文件)
(4)标签统计信息(生成 csv 文件)
2.小说评分分布(生成箱线图)
3.最受欢迎的小说出版社与标签(生成词云)
4.最受欢迎的小说出版社与标签(生成直方图)
5.高分小说中最受欢迎的出版社与标签(生成直方图)
6.出版社与标签关联分析(生成 txt 文件)
以上各项数据分析使用的分析方法:
1、2、4、5: 主要工具:pandas 库、matplotlib 库
过程:
- 分别生成 4 个 dataframe,分别为图书信息(不含标签)、高分图书信息 (不含标签)、图书标签、高分图书标签;
- 对图书信息(不含标签)与图书标签两个 dataframe 使用 describe()函数 得到统计信息并存为 csv 文件
- 通过 groupby 函数,得到各个 dataframe 中各出版社、标签出现次数,生 成直方图并保存
3(生成词云):
主要工具:wordcloud 库
过程:
- 分别将出版社和标签,以空格为分隔,形成字符串
- 通过 wordcloud 库的 WordCloud 对象分别生成两个词云并保存
6(出版社与标签关联分析):
主要工具:efficient_apriori 库
过程:
- 将每本小说的出版社与各个标签分别形成的元组存为列表
- 通过 efficient_apriori 库的 apriori 类进行分析,得到关联规则,输出并存 为 txt 文件
五、结果与可视化
1.小说统计信息
(1)评分统计信息(生成 csv 文件)
(2)作者统计信息(生成 csv 文件)
(3)出版社统计信息(生成 csv 文件)
(4)标签统计信息(生成 csv 文件)
2.小说评分分布(生成箱线图)
3.最受欢迎的小说出版社与标签(生成词云)
4.最受欢迎的小说出版社与标签(生成直方图)
5.高分小说中最受欢迎的出版社与标签(生成直方图)
6.出版社与标签关联分析(生成 txt 文件)
{东野圭吾} -> {南海出版公司} (conf: 0.718, supp: 0.004, lift: 9.447, conv: 3.276)
{推理} -> {南海出版公司} (conf: 0.240, supp: 0.004, lift: 3.162, conv: 1.216)
{日本文学} -> {南海出版公司} (conf: 0.323, supp: 0.005, lift: 4.251, conv: 1.365)
{日本} -> {南海出版公司} (conf: 0.311, supp: 0.006, lift: 4.090, conv: 1.341)
{南海出版公司} -> {小说} (conf: 0.113, supp: 0.009, lift: 0.968, conv: 0.996)
{北京联合出版公司} -> {小说} (conf: 0.117, supp: 0.004, lift: 0.995, conv: 0.999)
{经典} -> {人民文学出版社} (conf: 0.233, supp: 0.005, lift: 2.454, conv: 1.180)
{人民文学出版社} -> {小说} (conf: 0.111, supp: 0.011, lift: 0.943, conv: 0.992)
{中国} -> {人民文学出版社} (conf: 0.170, supp: 0.003, lift: 1.787, conv: 1.090)
{外国文学} -> {人民文学出版社} (conf: 0.121, supp: 0.006, lift: 1.278, conv: 1.030)
{中国文学} -> {人民文学出版社} (conf: 0.195, supp: 0.004, lift: 2.057, conv: 1.125)
{文学} -> {人民文学出版社} (conf: 0.103, supp: 0.004, lift: 1.088, conv: 1.009)
{北京十月文艺出版社} -> {小说} (conf: 0.125, supp: 0.004, lift: 1.066, conv: 1.009)
{译林出版社} -> {外国文学} (conf: 0.114, supp: 0.006, lift: 2.349, conv: 1.074)
{外国文学} -> {译林出版社} (conf: 0.129, supp: 0.006, lift: 2.349, conv: 1.085)
{译林出版社} -> {小说} (conf: 0.123, supp: 0.007, lift: 1.047, conv: 1.006)
{小说} -> {上海译文出版社} (conf: 0.102, supp: 0.012, lift: 1.055, conv: 1.006)
{上海译文出版社} -> {小说} (conf: 0.124, supp: 0.012, lift: 1.055, conv: 1.007)
{外国文学} -> {上海译文出版社} (conf: 0.209, supp: 0.010, lift: 2.158, conv: 1.142)
{上海译文出版社} -> {外国文学} (conf: 0.104, supp: 0.010, lift: 2.158, conv: 1.063)
{文学} -> {上海译文出版社} (conf: 0.143, supp: 0.006, lift: 1.473, conv: 1.053)
{湖南文艺出版社} -> {小说} (conf: 0.121, supp: 0.004, lift: 1.034, conv: 1.005)
{江苏凤凰文艺出版社} -> {小说} (conf: 0.117, supp: 0.004, lift: 1.001, conv: 1.000)
{上海文艺出版社} -> {小说} (conf: 0.116, supp: 0.003, lift: 0.990, conv: 0.999)
{新星出版社} -> {小说} (conf: 0.121, supp: 0.003, lift: 1.028, conv: 1.004)
六、结论
从数据分析与可视化的结果中,我们得出如下结论:
豆瓣读书“小说”标签下,按照综合排序前 1000 本小说具有这样的特征:
- 整体评分较高,平均评分为 8.37,但也有少数评分较低的小说,说明受欢迎的的小说大多为高分优质小说,但也有少量低分作品受到欢迎;
- 最受欢迎的作者、出版社、标签分别为东野圭吾、上海译文出版社以及“小说”;
- 比较最受欢迎的小说出版社与高分小说中最受欢迎的小说出版社,榜首几家出版社变化不大(上海译文出版社、人民文学出版社等出版社都是 名声大、作品质量高的出版社),说明这几个高质量的出版社受到欢迎;其余的出版社在两图中有相对明显差异,高分图书中文艺类出版社更常见,说明这几个文艺类出版社出版小说质量更佳却没有那么受欢迎;
- 比较最受欢迎的小说标签与高分小说中最受欢迎的小说标签,总体差异不大,大多为各国文学的标签。值得注意的是推理小说在最受欢迎的10个小说标签中出现,却没有在高分小说中最受欢迎的 10 个小说标签中出现,说明推理类小说虽受欢迎,总体质量相对其它文学类书籍较低;
- 从关联分析可知,最热门的几个出版社的最受欢迎的小说里,上海 译文出版社与译林出版社出版作品多为外国文学,人民文学出版社出版作品 则包括了各国作品,南海出版集团出版了较多的日本推理小说(尤其是东野圭吾的小说)并受到欢迎。
本文地址:https://blog.csdn.net/weixin_44102283/article/details/107252665
上一篇: tenda 无线路由器设置图解教程
下一篇: 这么漂亮礼金这么少为什么