Python 爬虫教程 | 豆瓣 TOP250 数据抓取与分析实战

一、项目背景与数据价值

豆瓣TOP250是影视行业的重要榜单,具有以下数据价值:

  • 评分与评价人数:衡量电影市场热度;

  • 导演与演员信息:分析人才价值与影视趋势;

  • 类型 / 地区 / 年份:洞察电影类型与年代变迁;

  • 经典台词:可用于 NLP 情感分析或推荐系统训练数据。


二、技术栈与环境配置

安装核心 Python 库:

pip install requests beautifulsoup4 pandas numpy matplotlib seaborn fake_useragent

版本建议:

应用场景版本要求
requests网络请求≥ 2.25
BeautifulSoupHTML 解析≥ 4.9
pandas数据处理≥ 1.2
fake_useragent伪装 User‑Agent≥ 1.1
time、random请求延时Python 标准库

三、网页结构深入解析

目标页面:https://movie.douban.com/top250。通过浏览器开发者工具(F12)分析页面结构存在以下关键点:

  • 电影单元数据 位于 <div class="item"> 内,包含标题、导演、评分等;

  • 翻页机制 使用参数 start=0, 25, … 225 控制页面切换 。


四、反爬策略与突破技巧

豆瓣可能设置以下反爬措施:

  1. User‑Agent 检测:使用 fake_useragent 随机生成请求头;

  2. 频率限制:结合 time.sleep()random.uniform() 实现随机延迟;

  3. IP 封锁防范:配置代理 IP 池,实现请求匿名化。

示例代码:

from fake_useragent import UserAgent
import random, timeheaders = {'User-Agent': UserAgent().random
}
time.sleep(random.uniform(1.5, 3.5))

五、完整代码实现

以下为完整爬虫流程,包括抓取、解析、异常处理和数据存储:

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import random
import re
from fake_useragent import UserAgentdef scrape_douban_top250():base_url = "https://movie.douban.com/top250?start={}"movies = []ua = UserAgent()for page in range(0, 250, 25):url = base_url.format(page)headers = {'User-Agent': ua.random,'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8','Connection': 'keep-alive','Referer': 'https://movie.douban.com/','Cookie': 'bid=123456789;'}try:print(f"正在抓取第{page // 25 + 1}页数据...")response = requests.get(url, headers=headers, timeout=15)response.encoding = 'utf-8'if response.status_code != 200:print(f"请求失败,状态码: {response.status_code}")continuesoup = BeautifulSoup(response.text, 'html.parser')grid_view = soup.find('ol', class_='grid_view')if not grid_view:print("未找到电影列表,可能页面结构有变化")continueitems = grid_view.find_all('li')for item in items:# 解析内容(排名、标题、导演、年份、地区、类型、评分、评价人数、经典台词)rank = item.find('em').text if item.find('em') else "N/A"title = item.find('span', class_='title').text.strip() if item.find('span', class_='title') else "未知标题"other_title = item.find('span', class_='other').text.strip() if item.find('span', class_='other') else ""bd = item.find('div', class_='bd')info_text = bd.find('p').get_text(strip=True).replace('\xa0', ' ') if bd and bd.find('p') else ""director = info_text.split("导演:")[1].split("主演")[0].strip().split('/')[0] if "导演:" in info_text else ""year = re.search(r'\d{4}', info_text).group(0) if re.search(r'\d{4}', info_text) else ""parts = info_text.split("/")region = parts[-2].strip() if len(parts) >= 2 else ""genre = parts[-1].strip() if len(parts) >= 1 else ""rating = item.find('span', class_='rating_num').text if item.find('span', class_='rating_num') else "0.0"star_div = item.find('div', class_='star')spans = star_div.find_all('span') if star_div else []votes = spans[3].text.replace('人评价', '') if len(spans) >= 4 else "0"quote = item.find('span', class_='inq').text if item.find('span', class_='inq') else ""movies.append({'排名': rank,'标题': title,'其他标题': other_title,'导演': director,'年份': year,'地区': region,'类型': genre,'评分': float(rating) if rating.replace('.', '', 1).isdigit() else 0.0,'评价人数': int(votes.replace(',', '')) if votes.isdigit() else 0,'经典台词': quote})print(f"成功抓取第{page // 25 + 1}页数据,共{len(movies)}条记录")time.sleep(random.uniform(3, 7))except Exception as e:print(f"第{page // 25 + 1}页抓取失败: {str(e)}")return pd.DataFrame(movies)df = scrape_douban_top250()
if not df.empty:df['年份'] = pd.to_numeric(df['年份'], errors='coerce').fillna(0).astype(int)df.to_csv('douban_top250.csv', index=False, encoding='utf-8-sig')print(f"数据抓取完成,共{len(df)}条记录,已保存至 douban_top250.csv")print("\n前 5 条数据预览:")print(df.head())
else:print("未抓取到任何数据,请检查网络或反爬策略是否生效")

代码亮点:

  • 随机延时防止被封;

  • 异常捕获增强稳定性;

  • 数据清洗:评分转为 float,票数转为 int;

  • 通过结构化字典构建 DataFrame 。


六、数据清洗与转换建议

建议在 DataFrame 构建后进一步处理:

df['year'] = df['year'].apply(lambda x: re.search(r'\d{4}', x).group() if re.search(r'\d{4}', x) else None)
df['director'] = df['director'].str.split('/').str[0]
df['quote'] = df['quote'].fillna('无')

这些能优化数据可用性,便于后续分析。


七、数据可视化分析范例

结合 Matplotlib 和 Seaborn,展示深度分析流程:

import matplotlib.pyplot as plt
import seaborn as snsplt.figure(figsize=(15,10))# 1. 评分分布直方图
plt.subplot(2,2,1)
sns.histplot(df['评分'], bins=20, kde=True)
plt.title('豆瓣TOP250评分分布')# 2. 年代趋势(TOP10)
plt.subplot(2,2,2)
sns.countplot(x='年份', data=df, order=df['年份'].value_counts().index[:10])
plt.xticks(rotation=45)
plt.title('电影上映年代分布TOP10')# 3. 导演上榜数TOP10
plt.subplot(2,2,3)
top_directors = df['导演'].value_counts().head(10)
sns.barplot(x=top_directors.values, y=top_directors.index)
plt.title('导演上榜作品数量TOP10')# 4. 评分与评价人数关系(对数坐标)
plt.subplot(2,2,4)
sns.scatterplot(x='评价人数', y='评分', data=df, hue='评分', palette='viridis')
plt.xscale('log')
plt.title('评分 vs 投票数(对数刻度)')plt.tight_layout()
plt.savefig('douban_analysis.png', dpi=300)

数据洞察:

  1. 评分偏左集中,均值约为 8.9,最低约 8.3;

  2. 1994–2004 年份涌现大量经典影片;

  3. 宫崎骏电影上榜数量最多,全胜导演之一;

  4. 投票数超过 150 万的影片评分均超过 9.0 。


八、常见问题与解决方案一览

问题现象解决方案
返回 403 内升级 UA 库、更换代理 IP
数据部分缺失添加备用 CSS 选择路径
爬取速度过慢缩短延时为 1–2 秒
pandas 中文乱码使用 encoding='utf-8-sig' 保存
请求超时增加重试机制或设置更高 timeout

九、项目拓展建议

  • 推荐系统构建:使用 TF-IDF 分析台词文本,构建内容推荐模型;

  • 自动定时更新:部署定时任务(如 crontab 或 Airflow)实现数据自动抓取与增量更新。


结语

本文全面涵盖了从豆瓣 TOP 250 数据 抓取 → 清洗 → 可视化 → 洞察 的完整流程,核心技巧包括:

  • 动态 UA 和代理 IP 破解反爬;

  • 稳定的异常处理机制;

  • 深度数据清洗与类型转换;

  • 多维数据分析洞察趋势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/94223.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/94223.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第04章 SPSS简介与数据库构建

参考&#xff1a;SPSS实战与统计思维 - 武松编著 - 微信读书 4.1 SPSS简介 发展历史 全称Statistical Product and Service Solutions&#xff0c;由美国斯坦福大学三位研究生于1968年开发。 对比其他软件成立时间&#xff1a;SAS&#xff08;1976年&#xff09;、Stata&…

【ABAP4】数据字典

ABAP数据字典ABAP数据字典概述数据字典的基本对象域数据元素表类型系统创建自定义透明表创建自定义结构锁对象ABAP数据字典概述 ABAP数据字典是SAP定义和管理数据的工具&#xff0c;包含了程序使用的所有对象&#xff0c;数据字典中包括数据库表、视图、数据类型、域、搜索帮助…

不知道Pycharm怎么安装?Pycharm安装教程(附安装包)

Pycharm安装教程&#xff08;附安装包&#xff09;获取方式&#xff1a;python开发工具包丨夸克网盘-资源免费下载 有位朋友刚开始学习python&#xff0c;不知道Pycharm要怎么安装&#xff0c;于是问我要一个安装教程。 先介绍一下Pycharm吧&#xff0c;PyCharm是一款python开…

在 Docker 容器中查看 Python 版本

博客目录前言方法一&#xff1a;交互式进入容器查看方法二&#xff1a;启动时直接执行命令方法三&#xff1a;启动后使用 exec 执行命令方法四&#xff1a;直接运行并查看版本&#xff08;容器退出&#xff09;方法比较与选择指南实际应用中的注意事项进阶技巧批量检查多个镜像…

React:Umi + React + Ant Design Pro的基础上接入Mock数据

为什么需要Mock数据 前端开发依赖后端接口时的阻塞问题 独立开发和测试的需求 快速迭代和原型验证的重要性 当前版本及框架 React18 Umi 4.0 Ant Design Ant Design Pro 其实这些都不重要&#xff0c;主要是有Umijs&#xff0c;因为Umijs具有开箱即用Mock功能的能力&#…

VMware centos磁盘容量扩容教程

目录前言相关概念磁盘磁盘分区文件系统挂载点物理卷、VG&#xff08;卷组&#xff09;、LV&#xff08;逻辑卷&#xff09;、LVM&#xff08;逻辑卷管理&#xff09;解决方案前言 这篇博客主要分享我在VM中通过docker搭建dify大模型应用平台时&#xff0c;遇到了分配的磁盘容量…

kubernetes中的认证和授权

一 kubernetes API 访问控制Authentication&#xff08;认证&#xff09;认证方式现共有8种&#xff0c;可以启用一种或多种认证方式&#xff0c;只要有一种认证方式通过&#xff0c;就不再进行其它方式的认证。通常启用X509 Client Certs和Service Accout Tokens两种认证方式。…

雅菲奥朗SRE知识墙分享(四):『AI已开始重塑劳动力市场,美国年轻科技从业者首当其冲』

近日&#xff0c;据《商业内幕》报道&#xff0c;AI正在重塑美国就业市场&#xff0c;年轻的科技从业者正首当其冲地感受到冲击。高盛首席经济学家Jan Hatzius在本周一撰文指出&#xff1a;“AI 确实开始在各类数据中显现出更加明显的迹象。”据高盛的分析&#xff0c;科技行业…

Python爬虫入门指南:从零开始的网络数据获取之旅

文章目录前言1. 什么是网络爬虫&#xff1f;2. 爬虫的伦理与法律边界3. Python爬虫的基本工具库3.1 Requests&#xff1a;HTTP请求库3.2 Beautiful Soup&#xff1a;HTML/XML解析库3.3 lxml&#xff1a;高效XML/HTML解析器3.4 Selenium&#xff1a;自动化浏览器工具4. 第一个爬…

说说你对JVM的垃圾回收机制的理解?

Java 虚拟机&#xff08;JVM&#xff09;的垃圾回收&#xff08;Garbage Collection&#xff0c;GC&#xff09;机制是自动管理内存的核心&#xff0c;其核心目标是识别并回收不再被使用的对象所占用的内存&#xff0c;避免内存泄漏和溢出。以下从垃圾判断方法、垃圾回收算法和…

兑换汽水瓶

实现代码&#xff1a;public static void main(String[] args) {Scanner in new Scanner(System.in);while (in.hasNextInt()) {int n in.nextInt();if (n 0) {break;}System.out.println(n / 2);}}

结合 Flutter 和 Rust 的跨平台开发方案

结合 Flutter 和 Rust 的跨平台开发方案 1. 核心思想 本方案的核心思想是Flutter 负责 UI,Rust 负责逻辑 。Flutter 作为一个成熟的 UI 框架,专注于渲染流畅、跨平台一致的用户界面。而将那些对性能、安全和并发有高要求的复杂业务逻辑、计算密集型任务或底层系统操作,全部…

理想汽车智驾方案介绍 2|MindVLA 方案详解

一、引言 MindVLA 主要包括空间智能模块、语言智能模块、动作策略模块、强化学习模块&#xff0c;这些模块分别有以下功能&#xff1a; 空间智能模块&#xff1a;输入为多模态传感器数据&#xff0c;使用 3D 编码器提取时空特征&#xff0c;然后将所有传感器与语义信息融合成…

计算机网络基础(三) --- TCP/IP网络结构(运输层)

运输层1. 概述和运输服务运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信功能, 运输层协议是在端系统中而不是路由器中实现的, 网络应用程序可以调用多种运输层协议, 如因特网的两种协议: TCP 和 UDP ,每种协议都能为调用的应用程序提供一组不同的运输层服务1.1 运输…

JdbcTemplate和MyBatis的区别

在 Java 后端开发中&#xff0c;JdbcTemplate&#xff08;Spring 框架提供&#xff09;和 MyBatis&#xff08;持久层框架&#xff09;都是用于简化数据库操作的工具&#xff0c;但它们的设计理念、使用方式、灵活性和适用场景有显著差异。下面从核心定位、核心特性、使用方式、…

埃氏筛|树dfs|差分计数

lc525把数组里的0换成-1&#xff0c;求子数组和为零的最长长度用哈希表记录前缀和首次出现的位置通过找相同前缀和的位置差得出最长的0和1数量相等的子数组长度。class Solution { public:int findMaxLength(vector<int>& nums) {unordered_map<int,int>hashta…

(JVM)Java 对象创建的完整过程

在日常开发和面试中&#xff0c;经常会被问到 “Java 中对象是如何被创建的&#xff1f;” 表面上只是一个 new 关键字&#xff0c;但 JVM 在幕后完成了一系列复杂操作。 可以总结为以下 六大步骤&#xff1a;类加载检查 → 分配内存 → 内存清零 → 设置对象头 → 执行构造函数…

数据库优化提速(三)JSON数据类型在酒店管理系统搜索—仙盟创梦IDE

在 MySQL 中&#xff0c;JSONB 类型&#xff08;MySQL 中实际为 JSON 类型&#xff0c;功能类似 PostgreSQL 的 JSONB&#xff0c;支持高效的 JSON 数据存储和查询&#xff09;非常适合存储半结构化数据&#xff0c;例如酒店入住客人的复杂信息&#xff08;包含客人基本信息、入…

小程序全局状态管理:使用MobX进行跨组件数据共享详解(九)

一、定义全局数据共享&#xff08;又叫&#xff1a;状态管理&#xff09;是为了解决组件之间数据共享的问题&#xff1b;全局数据共享方案&#xff1a;VueX、Redux、MobX等&#xff1b;二、小程序全局数据共享方案使用mobx-miniprogram配合mobx-miniprogram-bindings实现全局数…

生成模型 | DDPM -> Imrpoved DDPM -> DDIM

DDPM: Denoising Diffusion Probabilistic Models 采样过程中的迭代计算为&#xff1a; xt−11αt(xt−1−αt1−αˉϵθ(xt,t))β~tzx_{t-1} \frac{1}{\sqrt{\alpha_t}}(x_t - \frac{1 - \alpha_t}{\sqrt{1 - \bar{\alpha}}}\epsilon_{\theta}(x_t, t)) \sqrt{\tilde{\beta…