Python网络爬虫—对当当网关于python图书的数据分析
(一)选题背景
因为现如今的科技越来越发达,人们对于信息的获取道路变得更加宽广了,在以前的话,人们会受到空间,时间,科技等问题的阻碍,对于大部分知识只有在书籍当中才能够找到。不过随着现如今科技的进步,信息的载体也会变得越来越多,信息的传播方式也变得多种多样,电子书就可以通过图像、声音、文字来传播你想要的知识。还有就是电子书的传播形式更加便于人们去理解文字的意思,电子书可以通过图像、声音、文字来传播你所想要的东西,这对于单纯的书本上的文字来说,效果是要更好的。并且电子书上可以找到许多书籍,不用你自己去书店买就能够看到你想看的书,这也让人们的生活变得更加方便。
(二)设计方案
目的:爬取当当网关于python的图书,并将爬取到的数据保存到excel文档和sql数据库中,再通过可视化的柱状图扇形图散点图来对图书各方面价格出版社等属性进行分析。
方案:首先要使用requests模块进行当当网url的请求,获取到响应,然后用lxml模块解析获取到的响应,取出每一本书籍的书名,价格,作者,出版时间,出版社,书籍简介,通过pandas模块将取出的书籍信息保存到excel文档中,又通过pymysql模块连接数据库,将书籍信息保存到sql数据库里,数据保存成功之后,使用pandas读取excel文档制作出版社统计数据柱状图,关于价格的饼状图,出版社和出版时间的散点图。
技术难点:在解析数据时注意xpath的使用,准确拿捏到数据,存储数据时要注意拼接sql语句,制作图形时由于数据太多,要进行数据筛选,展示一部分数据。
(三)数据分析步骤
1、数据来源:http://search.dangdang.com/?key=python&act=input&sort_type=sort_sale_amt_desc#J_tab
2、数据清洗
由于当当网数据都是有规律的,不需要什么数据清洗。
1 df['价格'] = df['价格'].str.replace('¥', '') 2 df['价格'] = df['价格'].astype(float) 3 filtered_df = df[df['价格'] > 0]
制作饼状图时清理价格列数据,去除价格中的¥符号,将价格列转换为浮点型, 筛选出价格大于0的数据
3.大数据分析过程及采用的算法
1 # 爬取数据 2 start_url = f'{source_url}?key={key}&page_index={page}&sort_type=sort_sale_amt_desc#J_tab' 3 print(f"爬取第{page}页,该页url是:{start_url}") 4 response = requests.get(start_url) 5 data = response.text 6 print(data)
爬取网页后,拿到所有python书籍和信息
1 from lxml import etree 2 from pprint import pprint 3 for page in range(1, 6): 4 data = scrape_api(page) 5 # 所有数据保存到列表 6 items = [] 7 selector = etree.HTML(data) 8 lis = selector.xpath('//div[@class="con shoplist"]//li') 9 for li in lis: 10 # 书名 11 title = li.xpath('./a/@title')[0] 12 # 价格 13 price = li.xpath('.//p[contains(@class, "price")]/span[1]/text()')[0] 14 # 作者 15 author = li.xpath('.//a[@dd_name="单品作者"]/@title') 16 if author: 17 author = author[0] 18 else: 19 author = "" 20 # 出版时间 21 date = li.xpath('./p[@class="search_book_author"]/span[2]/text()') 22 if date: 23 date = date[0] 24 date = str(date).strip(' /') 25 else: 26 date = "" 27 # 出版社 28 publisher = li.xpath('.//a[@dd_name="单品出版社"]/@title')[0] 29 # 书籍简介 30 detail = li.xpath('./p[@class="detail"]/text()') 32 if detail: 33 detail = detail[0] 34 else: 35 detail = "" 36 item = { 37 'title': title, 38 'author': author, 39 'date': date, 40 'publisher': publisher, 41 'price': price, 42 'detail': detail 43 } 44 pprint(item)
提取想要的信息,书名、价格、作者、出版时间等等,由于数据量太多,提取信息后再对数据进行整理分析
将数据保存在excel中
1 import pymysql 2 import requests 3 from lxml import etree 4 import pandas as pd 5 items = [[] for x in range(6)] 6 for page in range(1, 2): 7 data = scrape_api(page) 8 datas = parse_data(data) 9 for data in datas: 10 data_list = [value for value in data.values()] 11 # 将value值加入到itmes列表,便于excel保存 12 for i in range(6): 13 items[i].append(data_list[i]) 14 excel_data = { 15 '书名': items[0], 16 '作者': items[1], 17 '出版时间': items[2], 18 '出版社': items[3], 19 '价格': items[4], 20 '书籍简介': items[5] 21 } 22 23 # 保存数据到excel 24 df = pd.DataFrame(excel_data) 25 df.to_excel('当当网python书籍数据.xlsx', index=False) 26 print("数据写入成功!!")
可以看到当当网上的python图书不仅有国内作者写的,也有国外的,价格也不贵,平均在50元左右,出版社则大多数是双一流大学,图书形式多种多样,有像小说一样的教学也有视频教学还有漫画式的教学,有适合才接触的新手的也有给高材生的,也有书本资源配套丰富和贫瘠的等等。
import pymysql import requests from lxml import etree for page in range(1, 2): data = scrape_api(page) datas = parse_data(data) for data in datas: # 保存数据到数据库 db = pymysql.connect(host='localhost', user='root', password='123456', port=3306, db='mydb') cursor = db.cursor() table = 'tb_books' keys = ', '.join(item.keys()) values = ', '.join(['%s'] * len(item)) sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table, keys=keys, values=values) try: if cursor.execute(sql, tuple(item.values())): print("数据插入成功") db.commit() except Exception as e: print(e) print("数据插入失败") db.rollback() db.close()
此外,我在最开始将数据保存到sql数据库中
保存到sql数据库的原因:因为网站图书的数据量庞大,如果超过excel容纳范围可用sql数据库
保存到excel的原因:直观看到爬取的书籍内容,并且可为后面可视化做准备
4、数据可视化
制作出版社和出版数量关系柱状图
1 import matplotlib.pyplot as plt 2 import numpy as np 3 import pandas as pd 4 # 读取Excel文件 5 df = pd.read_excel('当当网python书籍数据.xlsx') 6 publisher_counts = df['出版社'].value_counts() 7 plt.rcParams['font.sans-serif'] = 'simhei' 8 plt.rcParams['axes.unicode_minus'] = False 9 cmap = plt.get_cmap('tab20') 10 # 绘制柱状图 11 plt.bar(publisher_counts.index, publisher_counts.values, color=cmap(np.arange(len(publisher_counts)))) 12 plt.xlabel('出版社') 13 plt.ylabel('出版社个数') 14 plt.title('出版社统计') 15 plt.xticks(rotation=90, fontsize=9) 16 plt.show()
出版社最多的是清华大学,达到17个,北京大学则是相对最少的,可以联想到清华大学对python的教学教学质量最好也可以估计到清华大学的计算机专业也肯定是排在前面的。其次第二的是人民邮电大学,第三是水利水电出版社。
绘制价格饼状图
1 # 读取Excel文件 2 df = pd.read_excel('当当网python书籍数据.xlsx') 4 plt.rcParams['font.sans-serif'] = 'simhei' 5 plt.rcParams['axes.unicode_minus'] = False 7 #清理数据 8 df['价格'] = df['价格'].str.replace('¥', '') 9 df['价格'] = df['价格'].astype(float) 10 filtered_df = df[df['价格'] > 0] 11 subset_df = filtered_df.head(10) 12 price_counts = subset_df['价格'].value_counts() 13 plt.figure(figsize=(8, 6)) 15 # 绘制饼状图 16 plt.pie(price_counts, labels=price_counts.index, autopct='%1.1f%%') 17 plt.title('价格分布') 18 plt.legend(title='价格', loc='upper right', bbox_to_anchor=(0.7, 0, 0.5, 1)) 20 plt.show()
价格最多的是34.9元,占20%,是其他价位数量的两倍,大多数是一百以内的价格,最高价为178.5,最低价为34.9。
绘制散点图
1 df = pd.read_excel('当当网python书籍数据.xlsx') 2 plt.rcParams['font.sans-serif'] = 'simhei' 3 plt.rcParams['axes.unicode_minus'] = False 4 publish_time = pd.to_datetime(df['出版时间']) 5 publish_company = df['出版社'] 6 plt.figure(figsize=(10, 6)) 7 # 创建散点图 8 plt.plot(publish_time, publish_company, marker='o', linestyle='', label='出版社') 9 plt.xlabel('出版时间') 10 plt.ylabel('出版社') 11 plt.title('出版时间和出版社关系') 12 plt.legend() 13 plt.xticks(rotation=45) 14 plt.tight_layout() 15 plt.show()
从2019年出版社开始出版,最早开始出版的是机械工业出版社,2021年开始出版社开始增多,出版社最多的是清华大学,2023年也在持续出版
5.附完整程序源代码(以及输出结果)
1 import numpy as np 2 import pandas as pd 3 import pymysql 4 import requests 5 from lxml import etree 6 import matplotlib.pyplot as plt 7 8 9 # 爬取书籍关键字 10 key = "python" 11 # 初始url,用于拼接列表页url 12 source_url = 'http://search.dangdang.com/' 13 14 15 def scrape_api(page): 16 """ 17 请求当当网,获取响应 18 :return: 19 """ 20 # 构造请求地址 21 start_url = f'{source_url}?key={key}&page_index={page}&sort_type=sort_sale_amt_desc#J_tab' 22 print(f"爬取第{page}页,该页url是:{start_url}") 23 # 请求地址,获取响应 24 response = requests.get(start_url) 25 # 获取响应 26 data = response.text 27 # 将响应的数据返回 28 return data 29 30 31 def parse_data(data): 32 """ 33 解析请求当当网的数据 34 :return: 35 """ 36 # 所有数据保存到列表 37 items = [] 38 # 解析响应数据 39 selector = etree.HTML(data) 40 # 拿到列表页所有书籍 41 lis = selector.xpath('//div[@class="con shoplist"]//li') 42 # 遍历列表页所有书籍,取出每一本书籍的信息 43 for li in lis: 44 # 书名 45 title = li.xpath('./a/@title')[0] 46 # 价格 47 price = li.xpath('.//p[contains(@class, "price")]/span[1]/text()')[0] 48 # 作者 49 author = li.xpath('.//a[@dd_name="单品作者"]/@title') 50 if author: 51 author = author[0] 52 else: 53 author = "" 54 # 出版时间 55 date = li.xpath('./p[@class="search_book_author"]/span[2]/text()') 56 if date: 57 date = date[0] 58 date = str(date).strip(' /') 59 else: 60 date = "" 61 # 出版社 62 publisher = li.xpath('.//a[@dd_name="单品出版社"]/@title')[0] 63 # 书籍简介 64 detail = li.xpath('./p[@class="detail"]/text()') 65 # detail有时没有,结果None 66 if detail: 67 detail = detail[0] 68 else: 69 detail = "" 70 71 # 构造字典保存数据 72 item = { 73 'title': title, 74 'author': author, 75 'date': date, 76 'publisher': publisher, 77 'price': price, 78 'detail': detail 79 } 80 # 将数据添加到列表中 81 items.append(item) 82 83 # 将数据列表返回 84 return items 85 86 87 def create_database(): 88 """ 89 创建数据库 90 :return: 91 """ 92 # 连接数据库,password:自己的数据库密码 93 db = pymysql.connect(host='localhost', user='root', password='123456', port=3306) 94 # 创建名为mydb的数据库 95 cursor = db.cursor() 96 cursor.execute("CREATE DATABASE IF NOT EXISTS mydb DEFAULT CHARACTER SET utf8mb4") 97 db.close() 98 99 100 101 def create_table(): 102 """ 103 创建数据表 104 :return: 105 """ 106 # 连接数据库,password:自己的数据库密码 107 db = pymysql.connect(host='localhost', user='root', password='123456', port=3306, db='mydb') 108 cursor = db.cursor() 109 # 创建表tb_books 110 sql = 'create table IF NOT EXISTS tb_books (title varchar(521), author varchar(256), ' \ 111 'publisher varchar(255), date varchar(255), price varchar(255), detail TEXT)' 112 cursor.execute(sql) 113 db.close() 114 115 116 117 def save_data(item): 118 """ 119 保存数据到数据库 120 :param data: 每一条书籍信息 121 :return: 122 """ 123 # 连接数据库 124 db = pymysql.connect(host='localhost', user='root', password='123456', port=3306, db='mydb') 125 cursor = db.cursor() 126 table = 'tb_books' 127 # 取出保存在字典内的字段,进行sql语句拼接 128 keys = ', '.join(item.keys()) 129 values = ', '.join(['%s'] * len(item)) 130 sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table, keys=keys, values=values) 131 try: 132 if cursor.execute(sql, tuple(item.values())): 133 print("数据插入成功") 134 db.commit() 135 except Exception as e: 136 print(e) 137 print("数据插入失败") 138 db.rollback() 139 140 db.close() 141 142 143 def save_excel(file_name, data): 144 """ 145 保存数据 146 :param file_name: excel文件名字 147 :param data: 所有书本的信息 148 :return: 149 """ 150 df = pd.DataFrame(data) 151 df.to_excel(file_name, index=False) 152 print("数据写入成功!!") 153 154 155 def produce_bar(): 156 """ 157 制作出版社统计数据柱状图 158 :return: 159 """ 160 # 读取Excel文件 161 df = pd.read_excel('当当网python书籍数据.xlsx') 162 163 # 统计每个出版社的个数 164 publisher_counts = df['出版社'].value_counts() 165 166 # 设置字体和编码格式 167 plt.rcParams['font.sans-serif'] = 'simhei' 168 plt.rcParams['axes.unicode_minus'] = False 169 170 # 创建颜色映射 171 cmap = plt.get_cmap('tab20') # 使用tab20颜色映射,可以根据需求选择其他颜色映射 172 173 # 绘制柱状图 174 plt.bar(publisher_counts.index, publisher_counts.values, color=cmap(np.arange(len(publisher_counts)))) 175 176 # 设置横纵坐标标签 177 plt.xlabel('出版社') 178 plt.ylabel('出版社个数') 179 180 # 标题 181 plt.title('出版社统计') 182 183 # 自动调整横坐标标签旋转角度,以避免重叠 184 plt.xticks(rotation=90, fontsize=9) 185 186 # 显示图形 187 plt.show() 188 189 190 def produce_pi(): 191 """ 192 价格饼状图 193 :return: 194 """ 195 # 读取Excel文件 196 df = pd.read_excel('当当网python书籍数据.xlsx') 197 198 # 设置字体和编码格式 199 plt.rcParams['font.sans-serif'] = 'simhei' 200 plt.rcParams['axes.unicode_minus'] = False 201 202 # 清理价格列数据 203 df['价格'] = df['价格'].str.replace('¥', '') # 去除价格中的¥符号 204 df['价格'] = df['价格'].astype(float) # 将价格列转换为浮点型 205 206 # 筛选数据(可根据需要修改筛选条件) 207 filtered_df = df[df['价格'] > 0] # 筛选出价格大于0的数据 208 209 # 展示部分数据 210 subset_df = filtered_df.head(10) # 获取前10行数据 211 212 # 统计价格分布 213 price_counts = subset_df['价格'].value_counts() 214 215 # 绘制饼状图 216 plt.figure(figsize=(8, 6)) 217 plt.pie(price_counts, labels=price_counts.index, autopct='%1.1f%%') 218 plt.title('价格分布') 219 220 # 添加图例 221 plt.legend(title='价格', loc='upper right', bbox_to_anchor=(0.7, 0, 0.5, 1)) 222 223 plt.show() 224 225 226 def produce_point(): 227 """ 228 出版时间和出版社散点图 229 :return: 230 """ 231 # 读取Excel文件 232 df = pd.read_excel('当当网python书籍数据.xlsx') 233 234 # 设置字体和编码格式 235 plt.rcParams['font.sans-serif'] = 'simhei' 236 plt.rcParams['axes.unicode_minus'] = False 237 238 # 获取出版时间和出版社数据 239 publish_time = pd.to_datetime(df['出版时间']) 240 publish_company = df['出版社'] 241 242 # 创建散点图 243 plt.figure(figsize=(10, 6)) 244 plt.plot(publish_time, publish_company, marker='o', linestyle='', label='出版社') 245 plt.xlabel('出版时间') 246 plt.ylabel('出版社') 247 plt.title('出版时间和出版社关系') 248 plt.legend() 249 plt.xticks(rotation=45) # 旋转x轴刻度标签以提高可读性 250 plt.tight_layout() # 调整布局,防止标签重叠 251 plt.show() 252 253 254 255 # 保存excel数据列表 256 items = [[] for x in range(6)] 257 258 259 def main(): 260 """ 261 程序运行主函数 262 :return: 263 """ 264 # 创建数据库 265 create_database() 266 # 创建表 267 create_table() 268 # 构造页数,进行url拼接 269 for page in range(1, 6): 270 # 请求网址,获取响应 271 data = scrape_api(page) 272 # 解析响应数据 273 datas = parse_data(data) 274 # 遍历书籍数据列表,取出每条书籍数据 275 for data in datas: 276 # 保存数据到数据库 277 # save_data(data) 278 # 取出每条数据的value值 279 data_list = [value for value in data.values()] 280 # 将value值加入到itmes列表,便于excel保存 281 for i in range(6): 282 items[i].append(data_list[i]) 283 284 # 取出items每一个索引值内的数据,与excel列名一一对应 285 excel_data = { 286 '书名': items[0], 287 '作者': items[1], 288 '出版时间': items[2], 289 '出版社': items[3], 290 '价格': items[4], 291 '书籍简介': items[5] 292 } 293 294 # 保存数据到excel 295 save_excel('当当网python书籍数据.xlsx', excel_data) 296 297 298 if __name__ == '__main__': 299 # 执行主函数 300 main() 301 # 制作柱状图 302 produce_bar() 303 # 制作饼状图 304 produce_pi() 305 # 制作散点图 306 produce_point()
(四)总结
对本课程设计的整体完成情况做一个总结,包括:
1.通过对数据分析和挖掘,得到哪些有益的结论?是否达到预期的目标?
2.自己在完成此设计过程中,得到哪些收获?以及要改进的建议
通过这次对当当网书籍的爬取,让我自主练习和学习了网络爬虫的知识和能力,完成作业更加细致,体验了数据分析的乐趣,并且有用数据可视化来直观的观察.分析数据。这次作业的完成也激发了我对数据分析的学习热情,相信只要继续持续学习下去,我的数据分析知识储备和数据分析能力也会更近一步,同时也让我明白了在当今大数据,云计算,物联网,人工智能迅速发展的新时代,人们每天产生的数据蕴藏着巨大的价值,我也会更加努力的学好编程。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人