
简介这是一份面向爬虫入门与数据分析学习者的当当网畅销榜爬取与可视化项目资源涵盖数据采集、存储、清洗到图表展示的完整流程。项目基于Python编写包含爬虫脚本、数据预处理模块与可视化代码并配有近4年畅销图书榜单的Excel数据及交互式HTML图表适合希望系统性练习requests/Scrapy结合NoSQL数据库、并完成数据可视化实战的读者。压缩包共5个文件以3个py脚本为核心另含1个xlsx数据文件和1个html展示页面整体大小约266KB结构紧凑、便于逐文件拆解学习。目前已有165人浏览学习内容虽小但流程完整可直接运行查看效果也可作为课程设计或个人项目的参考模板。通过阅读源码读者能理解爬虫如何对接本地NoSQL数据库、数据清洗的常见处理方式以及如何用图表呈现排行趋势是兼顾代码实践与结果演示的轻量级学习素材。 想练爬虫又不想一上来就啃那种到处是妖魔鬼怪的加密参数那当当网的图书排行榜真的是一个特别合适的练手目标。页面结构规整、数据字段丰富、反爬门槛低更重要的是爬下来之后还能顺手做一轮可视化分析从数据里看出点有意思的门道。这篇文章我会把“当当网排行版爬虫可视化分析”整个项目从思路到落地拆开讲清楚包括字段设计、页面解析、数据清洗以及用pyecharts出图时的具体细节。这套流程不只是针对当当换到别的资讯类网站思路也是通用的。先说结论这个项目适合有一定Python基础、想完整走一遍“爬虫—清洗—存储—可视化”全流程的人。不需要你会JS逆向也不需要对Scrapy多熟requests加BeautifulSoup就能搞定。而且当当的排行榜数据是纯服务端渲染的不涉及异步加载对新手极其友好。1. 项目需求拆解与整体方案设计1.1 先想清楚这次到底要爬什么、解决什么问题很多人一上来就写代码结果爬到一半发现字段对不上、数据是乱的然后开始怀疑人生。我的习惯是先想清楚数据模型再动手。当当网的图书排行榜分为好几个榜单比如“24小时热销榜”“童书榜”“小说榜”“管理榜”每个榜单都包含排名、书名、作者、出版社、推荐指数、评论数、价格这些关键字段。我们这次爬的目标就是这些结构化信息然后基于这些信息回答几个问题哪本书卖得最火哪个出版社最强势图书定价集中在什么区间这些问题的答案就是可视化分析要呈现的核心内容。还有一个技术目标用最简方案跑通全流程。所以我选了requests加BeautifulSoup放弃Scrapy。原因是当当的排行榜页面量级很小根本不需要分布式和异步杀鸡不用牛刀。可视化部分用pyecharts因为它的中文文档友好、图表交互性好不需要写前端代码就能出HTML交互图。1.2 页面结构分析与数据字段设计当当图书排行榜的URL规律很明显请求参数基本都在路径里比如# 24小时热销榜第一页 http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-24h-0-0-1-1 # 页码体现在倒数第二个“1”上面改成2就是第二页项目标题虽然是“排行版”但实际页面就是传统的前后端不分离的HTML直接请求就能拿到完整数据。用浏览器打开页面按F12查看元素你会发现每本书都被包裹在ul.bang_list_mode的li节点里结构非常清晰。字段设计上我最终定了七个核心字段而不是全部照搬字段对应页面元素说明rankli标签内的classlist_num排名titleclassname下的a标签书名authorclassauthor作者信息publisher上述作者信息中的特定部分出版社priceclassprice下的span售价comment_numclassstar下的a标签评论数量recommendclassstar下的星级推荐指数这里有个坑作者那一栏包含了作者、译者、出版社等多个信息需要用正则去提取出版社而不能直接整段拿来用。这个细节我在后面的清洗部分会详细讲。2. 核心实现步骤从拿到页面到结构化数据2.1 请求模块为什么必须设置User-Agent请求代码本身很简单我直接贴当时跑通的版本import requests from bs4 import BeautifulSoup def get_html(url): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 } try: resp requests.get(url, headersheaders, timeout10) resp.raise_for_status() resp.encoding gbk return resp.text except requests.RequestException as e: print(f请求失败: {e}) return None这里有两个细节需要说明。第一User-Agent是必须的不设置的话服务器可以直接拒绝请求或者给你返回一个奇怪的页面。第二当当的页面编码是GBK不是UTF-8你需要在拿到响应后手动指定resp.encoding gbk否则后面的中文全是乱码。我之前见过不少人在这卡住明明用浏览器能看到页面代码解析就是一堆乱码就是因为没处理编码。这是一个典型的“经验比文档值钱”的细节。2.2 解析模块BeautifulSoup的实用选择器写法拿到HTML之后用BeautifulSoup解析。解析的核心就是找准DOM节点。我之前调试时打印过HTML发现每本书的节点规律是这样的所有书都在ul.bang_list_mode下每本书一个li。def parse_books(html): soup BeautifulSoup(html, lxml) book_list soup.select(ul.bang_list_mode li) books [] for item in book_list: rank item.select_one(.list_num).get_text(stripTrue) title item.select_one(.name a).get(title) author_info item.select_one(.author).get_text(stripTrue) price item.select_one(.price .price_n).get_text(stripTrue) comment_num item.select_one(.star a).get_text(stripTrue) star item.select_one(.level)[style] ...这里我推荐用lxml作为解析引擎速度比Python自带的html.parser快不少。select_one方法适合提取单个元素select适合提取列表两者搭配使用效率很高。还有一个值得说的点推荐指数不是直接给的文字而是一个style属性里面写了星级的百分比宽度比如width: 80%;需要自己换算成对应的星级。这也是爬虫有意思的地方不同网站对同一个信息的表达方式完全不一样你要学会灵活提取。3. 数据清洗与存储细节决定分析质量3.1 书名的清洗与字段拆分很多人爬完数据就直接做可视化结果图一出来卧槽怎么书名带了一堆“全彩”“典藏版”“精装”这类修饰词怎么同一个作者在不同书里格式还不一样。这就是数据清洗没做到位。我当时的做法是把获取到的原始数据先统一转成CSV格式然后用pandas做二次处理。这一步虽然多花了一些时间但后续分析省心很多。import pandas as pd # 把爬到的原始数据转成DataFrame df pd.DataFrame(books) # 去除书名两端的空白字符 df[title] df[title].str.strip() # 提取出版社author_info中括号里的内容 df[publisher] df[author_info].str.extract(r\[(.*?)\]) # 去掉作者信息中的出版社部分 df[author] df[author_info].str.replace(r\[.*?\], , regexTrue)出版社这种字段看似简单其实特别容易脏。同一个出版社可能叫“中信出版社”也可能叫“中信出版集团”这本质上是同一家。如果你要做出版社维度的统计建议先做一步映射统一否则柱状图会出现“一条数据两个柱子”的尴尬情况。3.2 评论数与价格的处理逻辑评论数量爬下来通常是“12345条评论”或者“(12345)”这种格式直接展示没问题但要做排序、做分析就不行了。处理方法是用正则把数字提取出来df[comment_num] df[comment_num].str.extract(r(\d)).astype(int)价格字段也一样爬下来的价格可能带着“¥”符号还有可能有促销价和原价混在一起的情况。我的建议是优先提取.price_n这个类名下的价格因为它是实际的促销价分析图书定价走势时更有参考价值。有些书显示“¥59.90”有些显示“¥39.90”统一去掉货币符号转成浮点数即可。另外强烈建议在做数据清洗的时候多打印df.info()和df.head()看看有没有NaN值有没有类型不对劲的列。爬虫项目最怕的就是数据都进了CSV结果类型还是字符串后续排序全是字符串排序逻辑完全错误。4. 可视化分析让排行榜会说话4.1 可视化工具选型为什么我选pyecharts数据可视化工具其实很多matplotlib、seaborn、plotly、pyecharts都可以。但对于这个项目我推荐pyecharts理由有三个第一pyecharts是国人开发的开源项目文档和社区都很友好遇到问题搜一下就能找到答案。第二它生成的图表是HTML文件可以交互鼠标移上去能看到具体数值体验比matplotlib生成的静态图片好很多。第三pyecharts天然支持中文不需要额外配置字体不会有matplotlib那种“中文变方块”的坑。安装也简单直接pip install pyecharts就行。唯一要注意的是需要把图表文件用render()方法输出成HTML文件然后浏览器打开看效果。4.2 四张核心图表的设计思路与实现我当时做了四张图每一张对应一个分析维度图一TOP10图书销量热度横向条形图这张图用横向条形图因为书名太长纵向柱状图会互相遮挡。排在前面的书基本能反映一个时期的热门趋势。我用Bar类翻转x轴和y轴配合reversal_axis()方法实现。from pyecharts.charts import Bar from pyecharts import options as opts bar ( Bar() .add_xaxis(top10[title].tolist()) .add_yaxis(评论数, top10[comment_num].tolist()) .reversal_axis() .set_global_opts( title_optsopts.TitleOpts(title当当图书排行榜TOP10), xaxis_optsopts.AxisOpts(name评论数), yaxis_optsopts.AxisOpts(name书名) ) ) bar.render(top10_bar.html)图二图书价格区间分布直方图做这张图之前先用pd.cut()对价格做分箱比如0-20、20-40这样区间然后统计每个区间的图书数量。可以看出图书的主要定价区间以及畅销书集中在哪个价格带。bins [0, 20, 40, 60, 80, 100, 200] df[price_bin] pd.cut(df[price], binsbins) price_group df.groupby(price_bin, observedTrue).size()图三出版社上榜次数TOP10统计每个出版社出现在排行榜上的次数可以直观看出哪个出版社的图书更畅销。这种图表用柱状图或者饼图都行。我建议用柱状图因为出版社名字本身也长纵向柱状图可以展示更多信息。图四评论数TOP20与推荐指数的散点图这个图用来观察图书的热度与质量之间的关系。X轴是评论数Y轴是推荐指数点的大小可以映射为价格。散点图适合探索数据之间的相关性比如是不是评论越多推荐指数越高。在pyecharts中可以用Scatter和set_global_opts配合visualmap_opts完成。4.3 可视化输出与部署的注意事项图表生成之后会自动打开一个HTML文件你可以把它分享给身边的人看也可以进一步集成到一个网页中。如果要做成定时任务比如每天自动爬取一次数据并生成最新图表可以把整个爬虫和分析脚本打包成一个.py文件然后用系统自带的定时任务去运行。需要注意的一点是pyecharts生成HTML时会有BOM头部分软件打开会显示乱码实际上浏览器打开完全没问题。如果你要直接把图表嵌入到Flask等Web应用里建议用Page对象把多个图表组合起来再一起渲染。5. 实操中的常见问题与排查实录5.1 爬虫运行没输出但exit code是0这个问题在热搜词里能看到就是“pycharm爬虫只显示proceed finished with exit code 0”。太经典了我早期也遇到过代码没报错但就是什么数据都没有。排查思路很直接第一步先在代码里加几个print把响应状态码打印出来看请求到底成没成功第二步把resp.text打印出来看是不是被反爬了第三步检查BeautifulSoup的select选择器确认页面里的class名称跟你代码里的一致。很多时候是页面改版了class名变了选择器匹配不到任何元素程序自然“顺利结束”。5.2 编码问题导致的乱码如果你用resp.encoding utf-8解析拿到的基本上全是乱码。这个前面已经说过了当当走的是GBK编码。但这里有一个更稳妥的判断方法用requests的apparent_encoding属性去自动识别编码。resp.encoding resp.apparent_encoding这个方法会基于响应内容自动判断编码对新手来说更保险。不过在运行前要注意如果结果还是乱码那就手动指定gbk。5.3 请求频率控制与简单反爬应对当当对这个榜单页面的反爬不算强但如果你请求频率过高依然会触发限流表现是返回一个验证页面或者直接超时。我的建议是每次请求之间加一个sleep(2)保证爬取间隔不要低于1秒。如果只是爬几个榜单页面总共也就几十次请求完全没必要担心。注意爬虫要保持克制。本项目仅用于学习和技术研究不构成对目标网站的恶意访问。大量并发请求会给对方服务器带来压力严格遵守robots协议被抓了不要怪我没提醒。5.4 数据量少时可视化效果差有时候排行榜就几十条数据图表做出来很空。我的做法是把多个榜单合并起来分析比如把24小时榜、童书榜、小说榜的数据都爬下来再统一分析。这样既能看到单榜的特征也能做跨榜单的横向对比数据量也从几十条扩大到了几百条图表的呈现效果更饱满。在实际操作中你会发现爬虫只是第一步真正花时间的往往是数据理解、清洗、可视化这一套组合拳。数据没清洗干净再好看的图表也是垃圾进垃圾出。但如果每一步都扎实最后出来的成果自己看着都开心拿出去分享也很有说服力。这个项目做完之后后续还可以继续扩展比如接入定时任务每天自动抓取并追踪榜单排名变化比如用自然语言处理对书名做关键词提取看看哪类题材最近比较火再比如把结果部署到Web端做成一个“当当图书排行榜实时看板”。每一步扩展都能学到新东西这才是我觉得这个练手项目真正值钱的地方。本文还有配套的精品资源点击获取