多线程爬虫 + 数据可视化——爬取豆瓣Top250并生成统计图
2026/6/15 6:01:49 网站建设 项目流程

之前的文章都是单线程爬取,速度有限。如果爬取几千上万条数据,单线程可能要等几分钟甚至几十分钟。本文以豆瓣 Top250 为例,使用多线程 + 数据可视化,爬完数据后直接生成统计图。

一、多线程爬虫是什么

单线程就像一个人在搬砖,多线程就是多个人同时搬砖

对比单线程多线程(4线程)
爬取250条数据~10秒~3秒
原理爬完一页再爬下一页4页同时爬
代码复杂度简单稍复杂

Python 中用concurrent.futures.ThreadPoolExecutor实现,使用非常简单。

二、核心实现

fromconcurrent.futuresimportThreadPoolExecutor,as_completedimportrequestsfromlxmlimportetree HEADERS={'User-Agent':'Mozilla/5.0'}BASE_URL="https://movie.douban.com/top250?start={}&filter="defscrape_page(page):"""爬取单页(25条)"""url=BASE_URL.format(page*25)resp=requests.get(url,headers=HEADERS,timeout=10)resp.encoding="utf-8"tree=etree.HTML(resp.text)movies=[]items=tree.xpath('//ol[@class="grid_view"]/li')foriteminitems:rank=item.xpath('.//em/text()')[0]title=item.xpath('.//span[@class="title"]/text()')[0]rating=item.xpath('.//span[@class="rating_num"]/text()')[0]people_text=item.xpath('.//span[contains(text(), "人评价")]/text()')people=people_text[0].strip()ifpeople_textelse"0人评价"movies.append({"rank":int(rank),"title":title,"rating":float(rating),"people":people})returnmoviesdefcrawl_all():"""多线程爬取全部10页"""all_movies=[]withThreadPoolExecutor(max_workers=5)asexecutor:# 提交所有任务futures={executor.submit(scrape_page,page):pageforpageinrange(10)}# 收集结果forfutureinas_completed(futures):page=futures[future]try:movies=future.result()all_movies.extend(movies)print(f"第{page+1}页完成,当前共{len(all_movies)}条")exceptExceptionase:print(f"第{page+1}页失败:{e}")# 按排名排序all_movies.sort(key=lambdax:x["rank"])returnall_movies

运行

importtime start=time.time()movies=crawl_all()print(f"\n爬取完成!共{len(movies)}条,耗时{time.time()-start:.1f}秒")

输出效果:

第1页完成,当前共25条 第4页完成,当前共50条 第2页完成,当前共75条 第3页完成,当前共100条 ... 爬取完成!共250条,耗时2.8秒

三、数据统计分析

爬完数据后用 pandas 分析一下:

importpandasaspd df=pd.DataFrame(movies)# 评分分布统计print("评分统计:")print(df["rating"].describe())# 评分最高的10部print("\n评分最高的10部:")print(df.head(10)[["rank","title","rating"]])# 评分区间分布print("\n评分区间分布:")foriinrange(4,10):count=len(df[(df["rating"]>=i)&(df["rating"]<i+1)])print(f"{i}~{i+1}分:{count}部")

四、数据可视化(matplotlib)

将统计结果生成图表,直观展示数据分布:

importmatplotlib.pyplotaspltimportmatplotlib matplotlib.rc('font',family='Microsoft YaHei')# 显示中文matplotlib.use('Agg')# 兼容无界面环境defplot_rating_distribution(df):"""评分分布柱状图"""# 统计各评分区间的电影数量bins=[i/2foriinrange(16,22)]# 8.0 ~ 10.0labels=[f"{bins[i]:.1f}~{bins[i+1]:.1f}"foriinrange(len(bins)-1)]counts=[]foriinrange(len(bins)-1):count=len(df[(df["rating"]>=bins[i])&(df["rating"]<bins[i+1])])counts.append(count)plt.figure(figsize=(10,6))bars=plt.bar(labels,counts,color='#1f77b4',alpha=0.8)plt.title('豆瓣电影Top250 评分分布',fontsize=16)plt.xlabel('评分区间',fontsize=12)plt.ylabel('电影数量',fontsize=12)# 在柱子上标出数字forbar,countinzip(bars,counts):plt.text(bar.get_x()+bar.get_width()/2,bar.get_height()+1,str(count),ha='center',fontsize=10)plt.tight_layout()plt.savefig('豆瓣评分分布.png',dpi=100)plt.close()print("图表已保存: 豆瓣评分分布.png")defplot_top10_bar(df):"""评分最高10部电影的横向柱状图"""top10=df.head(10)plt.figure(figsize=(10,8))bars=plt.barh(top10["title"],top10["rating"],color='#ff7f0e',alpha=0.8)plt.title('豆瓣电影Top250 评分最高Top10',fontsize=16)plt.xlabel('评分',fontsize=12)plt.xlim(9.0,10.0)# 在柱子旁标出分數forbar,ratinginzip(bars,top10["rating"]):plt.text(bar.get_width()+0.02,bar.get_y()+bar.get_height()/2,str(rating),va='center',fontsize=10)plt.tight_layout()plt.savefig('豆瓣评分Top10.png',dpi=100)plt.close()print("图表已保存: 豆瓣评分Top10.png")

完整主程序

importtimeif__name__=="__main__":start=time.time()# 1. 多线程爬取movies=crawl_all()print(f"爬取完成!共{len(movies)}条,耗时{time.time()-start:.1f}秒\n")# 2. 转为 DataFramedf=pd.DataFrame(movies)# 3. 输出统计print(df["rating"].describe())# 4. 生成图表plot_rating_distribution(df)plot_top10_bar(df)print(f"\n全部完成!总耗时{time.time()-start:.1f}秒")

五、多线程 vs 单线程速度对比

方式耗时速度提升
单线程(逐页爬)~10秒基准
多线程(5线程)~2.8秒快3~4倍
多线程(10线程)~1.5秒快6~7倍

六、踩坑提醒

1. 线程数不是越多越好

线程数超过 10 后速度提升不明显,反而可能被网站封 IP。建议5~8 个线程

2. 多线程爬取顺序是乱的

多线程执行时页面返回顺序不确定,最后需要按排名排序:

movies.sort(key=lambdax:x["rank"])

3. Matplotlib 中文乱码

添加以下配置解决:

matplotlib.rc('font',family='Microsoft YaHei')matplotlib.rc('axes',unicode_minus=False)

总结

多线程爬虫 + 数据可视化是爬虫开发的进阶技能。多线程大幅提升爬取效率,可视化让分析结果一目了然。这套思路不仅适用于豆瓣,也适用于任何需要大规模数据采集+展示的场景。


如果对你有帮助,欢迎点赞、评论、关注【张老师技术栈】,持续分享 Java/Python/爬虫 实战干货。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询