1. 为什么需要构建个人电影数据库每次想找部好电影看的时候你是不是也经常遇到这种情况打开豆瓣TOP250页面翻来翻去却记不清哪些已经看过哪些评分更高或者突然想起某部电影的情节却死活想不起片名这时候如果有个自己的电影数据库就方便多了。我最早也是手动整理Excel表格但每次更新都要复制粘贴特别麻烦。后来发现用Python爬取豆瓣数据再存到数据库里不仅能自动更新还能实现复杂查询。比如找出评分9分以上的美国犯罪片、显示还没看过的TOP50电影等等。这个项目特别适合影迷想系统化管理观影记录学习Python爬虫的实战案例需要数据可视化练手的数据爱好者实测下来用BeautifulSoupSQLite的方案既轻量又灵活手机电脑都能访问。下面我就带你从零开始一步步构建这个实用工具。2. 环境准备与基础爬取2.1 安装必要的库首先确保你的Python环境已经安装这些库pip install beautifulsoup4 requests lxml sqlalchemy我推荐用lxml作为解析器比标准库的html.parser速度更快。SQLAlchemy则是为了更方便地操作数据库避免直接写SQL语句的麻烦。2.2 分析豆瓣页面结构打开豆瓣TOP250页面按F12查看网页源码。你会发现每部电影的信息都包裹在li标签中关键信息分布很有规律电影名在span classtitle评分在span classrating_num详情链接在a href...海报图片在img src...用这个基础爬取代码就能获取第一页数据import requests from bs4 import BeautifulSoup url https://movie.douban.com/top250 headers {User-Agent: Mozilla/5.0} response requests.get(url, headersheaders) soup BeautifulSoup(response.text, lxml) for item in soup.find_all(div, class_item): title item.find(span, class_title).text rating item.find(span, class_rating_num).text print(f{title}: {rating})3. 数据清洗与结构化3.1 处理异常数据实际爬取时会遇到各种意外情况有些电影没有副标题部分电影缺少简介个别评分显示为暂无这就需要增加异常处理def safe_extract(element, attrNone): try: return element.text if not attr else element[attr] except (AttributeError, KeyError): return None3.2 转换数据格式原始数据都是字符串存入数据库前需要转换import re def clean_data(movie): # 提取评分中的数字 movie[rating] float(re.search(r\d\.?\d*, movie[rating]).group()) # 转换评价人数 100人评价 → 100 movie[votes] int(re.search(r\d, movie[votes]).group()) # 处理空值 movie[quote] movie.get(quote) or 无简介 return movie3.3 获取详情页数据要构建完整数据库还需要爬取详情页的导演/主演信息电影类型片长上映日期剧情简介这里有个小技巧豆瓣的详情页URL就是主页面中a标签的href属性值。4. 数据库设计与存储4.1 SQLite数据库设计我设计的movies表结构如下from sqlalchemy import create_engine, Column, Integer, String, Float from sqlalchemy.ext.declarative import declarative_base Base declarative_base() class Movie(Base): __tablename__ movies id Column(Integer, primary_keyTrue) title Column(String(100), nullableFalse) year Column(Integer) rating Column(Float) votes Column(Integer) director Column(String(50)) genres Column(String(100)) duration Column(String(20)) summary Column(String(500)) poster_url Column(String(200))4.2 批量插入数据使用SQLAlchemy的session批量操作from sqlalchemy.orm import sessionmaker engine create_engine(sqlite:///movies.db) Session sessionmaker(bindengine) session Session() # 假设movies_list是清洗后的数据列表 for data in movies_list: movie Movie(**data) session.add(movie) session.commit()4.3 数据去重策略防止重复插入的小技巧existing {m.title for m in session.query(Movie.title)} new_movies [m for m in movies_list if m[title] not in existing]5. 高级功能实现5.1 自动更新机制用定时任务每周更新一次import schedule import time def weekly_update(): # 爬取最新数据 # 比较并更新数据库 schedule.every().sunday.do(weekly_update) while True: schedule.run_pending() time.sleep(3600) # 每小时检查一次5.2 数据可视化用PandasMatplotlib生成统计图表import pandas as pd import matplotlib.pyplot as plt df pd.read_sql(SELECT * FROM movies, engine) # 评分分布直方图 df[rating].hist(bins10) plt.title(豆瓣TOP250评分分布) plt.show()5.3 构建查询接口用Flask快速搭建Web界面from flask import Flask, render_template app Flask(__name__) app.route(/) def index(): movies session.query(Movie).order_by(Movie.rating.desc()).limit(50) return render_template(index.html, moviesmovies)6. 项目优化与扩展6.1 反爬虫策略应对豆瓣有基本的反爬措施需要设置随机User-Agent添加请求延迟使用代理IP池from fake_useragent import UserAgent import random import time ua UserAgent() headers {User-Agent: ua.random} time.sleep(random.uniform(1, 3))6.2 数据备份方案定期备份数据库到云端import datetime import shutil def backup_db(): today datetime.datetime.now().strftime(%Y%m%d) shutil.copy2(movies.db, fbackups/movies_{today}.db)6.3 扩展其他数据源除了豆瓣TOP250还可以整合豆瓣新片榜IMDB Top 100烂番茄新鲜度建立更全面的电影评价体系。7. 实际应用场景这个数据库可以支持很多实用功能个人观影记录管理电影推荐系统影评数据分析导演/演员作品统计比如查询诺兰导演的高分电影nolan_movies session.query(Movie).filter( Movie.director.like(%诺兰%), Movie.rating 9.0 ).all()我在实际使用中发现配合Jupyter Notebook做数据分析特别方便。你可以随时查询特定类型的电影或者分析不同年份的评分分布。构建过程中最大的教训是一定要做好异常处理。网络请求失败、页面结构变化、数据格式异常等情况都会导致程序中断。我现在会在关键步骤都加上try-catch和日志记录确保程序能稳定运行。
BeautifulSoup实战:从豆瓣TOP250到构建个人电影数据库
发布时间:2026/6/20 20:05:50
1. 为什么需要构建个人电影数据库每次想找部好电影看的时候你是不是也经常遇到这种情况打开豆瓣TOP250页面翻来翻去却记不清哪些已经看过哪些评分更高或者突然想起某部电影的情节却死活想不起片名这时候如果有个自己的电影数据库就方便多了。我最早也是手动整理Excel表格但每次更新都要复制粘贴特别麻烦。后来发现用Python爬取豆瓣数据再存到数据库里不仅能自动更新还能实现复杂查询。比如找出评分9分以上的美国犯罪片、显示还没看过的TOP50电影等等。这个项目特别适合影迷想系统化管理观影记录学习Python爬虫的实战案例需要数据可视化练手的数据爱好者实测下来用BeautifulSoupSQLite的方案既轻量又灵活手机电脑都能访问。下面我就带你从零开始一步步构建这个实用工具。2. 环境准备与基础爬取2.1 安装必要的库首先确保你的Python环境已经安装这些库pip install beautifulsoup4 requests lxml sqlalchemy我推荐用lxml作为解析器比标准库的html.parser速度更快。SQLAlchemy则是为了更方便地操作数据库避免直接写SQL语句的麻烦。2.2 分析豆瓣页面结构打开豆瓣TOP250页面按F12查看网页源码。你会发现每部电影的信息都包裹在li标签中关键信息分布很有规律电影名在span classtitle评分在span classrating_num详情链接在a href...海报图片在img src...用这个基础爬取代码就能获取第一页数据import requests from bs4 import BeautifulSoup url https://movie.douban.com/top250 headers {User-Agent: Mozilla/5.0} response requests.get(url, headersheaders) soup BeautifulSoup(response.text, lxml) for item in soup.find_all(div, class_item): title item.find(span, class_title).text rating item.find(span, class_rating_num).text print(f{title}: {rating})3. 数据清洗与结构化3.1 处理异常数据实际爬取时会遇到各种意外情况有些电影没有副标题部分电影缺少简介个别评分显示为暂无这就需要增加异常处理def safe_extract(element, attrNone): try: return element.text if not attr else element[attr] except (AttributeError, KeyError): return None3.2 转换数据格式原始数据都是字符串存入数据库前需要转换import re def clean_data(movie): # 提取评分中的数字 movie[rating] float(re.search(r\d\.?\d*, movie[rating]).group()) # 转换评价人数 100人评价 → 100 movie[votes] int(re.search(r\d, movie[votes]).group()) # 处理空值 movie[quote] movie.get(quote) or 无简介 return movie3.3 获取详情页数据要构建完整数据库还需要爬取详情页的导演/主演信息电影类型片长上映日期剧情简介这里有个小技巧豆瓣的详情页URL就是主页面中a标签的href属性值。4. 数据库设计与存储4.1 SQLite数据库设计我设计的movies表结构如下from sqlalchemy import create_engine, Column, Integer, String, Float from sqlalchemy.ext.declarative import declarative_base Base declarative_base() class Movie(Base): __tablename__ movies id Column(Integer, primary_keyTrue) title Column(String(100), nullableFalse) year Column(Integer) rating Column(Float) votes Column(Integer) director Column(String(50)) genres Column(String(100)) duration Column(String(20)) summary Column(String(500)) poster_url Column(String(200))4.2 批量插入数据使用SQLAlchemy的session批量操作from sqlalchemy.orm import sessionmaker engine create_engine(sqlite:///movies.db) Session sessionmaker(bindengine) session Session() # 假设movies_list是清洗后的数据列表 for data in movies_list: movie Movie(**data) session.add(movie) session.commit()4.3 数据去重策略防止重复插入的小技巧existing {m.title for m in session.query(Movie.title)} new_movies [m for m in movies_list if m[title] not in existing]5. 高级功能实现5.1 自动更新机制用定时任务每周更新一次import schedule import time def weekly_update(): # 爬取最新数据 # 比较并更新数据库 schedule.every().sunday.do(weekly_update) while True: schedule.run_pending() time.sleep(3600) # 每小时检查一次5.2 数据可视化用PandasMatplotlib生成统计图表import pandas as pd import matplotlib.pyplot as plt df pd.read_sql(SELECT * FROM movies, engine) # 评分分布直方图 df[rating].hist(bins10) plt.title(豆瓣TOP250评分分布) plt.show()5.3 构建查询接口用Flask快速搭建Web界面from flask import Flask, render_template app Flask(__name__) app.route(/) def index(): movies session.query(Movie).order_by(Movie.rating.desc()).limit(50) return render_template(index.html, moviesmovies)6. 项目优化与扩展6.1 反爬虫策略应对豆瓣有基本的反爬措施需要设置随机User-Agent添加请求延迟使用代理IP池from fake_useragent import UserAgent import random import time ua UserAgent() headers {User-Agent: ua.random} time.sleep(random.uniform(1, 3))6.2 数据备份方案定期备份数据库到云端import datetime import shutil def backup_db(): today datetime.datetime.now().strftime(%Y%m%d) shutil.copy2(movies.db, fbackups/movies_{today}.db)6.3 扩展其他数据源除了豆瓣TOP250还可以整合豆瓣新片榜IMDB Top 100烂番茄新鲜度建立更全面的电影评价体系。7. 实际应用场景这个数据库可以支持很多实用功能个人观影记录管理电影推荐系统影评数据分析导演/演员作品统计比如查询诺兰导演的高分电影nolan_movies session.query(Movie).filter( Movie.director.like(%诺兰%), Movie.rating 9.0 ).all()我在实际使用中发现配合Jupyter Notebook做数据分析特别方便。你可以随时查询特定类型的电影或者分析不同年份的评分分布。构建过程中最大的教训是一定要做好异常处理。网络请求失败、页面结构变化、数据格式异常等情况都会导致程序中断。我现在会在关键步骤都加上try-catch和日志记录确保程序能稳定运行。