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.自己在完成此设计过程中,得到哪些收获?以及要改进的建议

通过这次对当当网书籍的爬取,让我自主练习和学习了网络爬虫的知识和能力,完成作业更加细致,体验了数据分析的乐趣,并且有用数据可视化来直观的观察.分析数据。这次作业的完成也激发了我对数据分析的学习热情,相信只要继续持续学习下去,我的数据分析知识储备和数据分析能力也会更近一步,同时也让我明白了在当今大数据,云计算,物联网,人工智能迅速发展的新时代,人们每天产生的数据蕴藏着巨大的价值,我也会更加努力的学好编程。

posted @   叉烧仙草蜜  阅读(1208)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示