news 2026/6/13 23:09:53

手把手教你用Xpath爬取豆瓣电影Top250:从分析页面结构到数据存储的完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你用Xpath爬取豆瓣电影Top250:从分析页面结构到数据存储的完整流程

零基础实战:用Xpath精准抓取豆瓣电影Top250全流程指南

豆瓣电影Top250榜单作为互联网上最具公信力的电影评分集合之一,包含了影史经典与当代佳作。对于数据分析爱好者而言,这个列表不仅是观影指南,更是绝佳的数据分析素材。本文将带你从零开始,使用Python中最高效的lxml库配合Xpath语法,完整实现榜单数据的自动化采集。

1. 环境准备与目标分析

在开始编写爬虫之前,我们需要先搭建好开发环境。推荐使用Python 3.8+版本,这是目前最稳定的Python发行版。关键依赖库包括:

pip install lxml requests pandas
  • lxml:高性能HTML/XML解析库,支持Xpath 1.0语法
  • requests:简洁优雅的HTTP请求库
  • pandas:数据处理的瑞士军刀,用于最终的数据存储

提示:为避免对目标网站造成过大访问压力,建议在代码中添加适当的延时(如3-5秒/页),并设置合理的User-Agent头部。

豆瓣Top250页面结构非常规整,每页展示25部电影,共10页。我们需要提取的核心数据字段包括:

字段名Xpath定位特征数据类型
电影名称class为"title"的span标签字符串
评分class为"rating_num"的span标签浮点数
评价人数包含"人评价"文本的div整数
经典台词class为"quote"的span标签字符串
详情链接a标签的href属性URL

2. 页面结构深度解析

打开豆瓣电影Top250页面(https://movie.douban.com/top250),右键选择"检查"进入开发者工具。通过元素检查器可以发现,每部电影信息都包裹在一个class为"item"的div中,这将成为我们定位的基准点。

关键DOM结构如下:

<ol class="grid_view"> <li> <div class="item"> <div class="info"> <div class="hd"> <a href="..."> <span class="title">电影名称</span> </a> </div> <div class="bd"> <div class="star"> <span class="rating_num">9.6</span> <span>1234567人评价</span> </div> <p class="quote"> <span class="inq">经典台词</span> </p> </div> </div> </div> </li> <!-- 其他24部电影结构相同 --> </ol>

基于此结构,我们可以设计出精准的Xpath表达式:

  • 电影名称://div[@class='item']//span[@class='title'][1]/text()
  • 评分://div[@class='item']//span[@class='rating_num']/text()
  • 评价人数://div[@class='item']//div[@class='star']/span[last()]/text()
  • 经典台词://div[@class='item']//span[@class='inq']/text()
  • 详情链接://div[@class='item']//div[@class='hd']/a/@href

注意:电影名称有两个span元素(中文名和原名),我们通常只需要中文名,因此添加了[1]索引。

3. 核心爬取代码实现

下面我们分步骤实现完整的爬取逻辑。首先是基础请求函数:

import requests from lxml import html import time import pandas as pd HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } def get_page(url): """获取页面HTML内容""" try: resp = requests.get(url, headers=HEADERS) resp.raise_for_status() return resp.text except requests.exceptions.RequestException as e: print(f"请求失败: {e}") return None

接下来是解析单页电影数据的核心函数:

def parse_page(html_content): """解析单页电影数据""" tree = html.fromstring(html_content) movies = [] for item in tree.xpath('//div[@class="item"]'): movie = { 'title': item.xpath('.//span[@class="title"][1]/text()')[0], 'rating': float(item.xpath('.//span[@class="rating_num"]/text()')[0]), 'votes': int(item.xpath('.//div[@class="star"]/span[last()]/text()')[0].replace('人评价', '')), 'quote': item.xpath('.//span[@class="inq"]/text()')[0] if item.xpath('.//span[@class="inq"]/text()') else '', 'url': item.xpath('.//div[@class="hd"]/a/@href')[0] } movies.append(movie) return movies

处理分页逻辑时,我们观察到豆瓣的翻页URL规律明显:

第1页:https://movie.douban.com/top250 第2页:https://movie.douban.com/top250?start=25&filter= 第3页:https://movie.douban.com/top250?start=50&filter= ...

基于此规律,我们可以构建完整的分页爬取流程:

def crawl_top250(): """爬取完整Top250榜单""" base_url = "https://movie.douban.com/top250" all_movies = [] for start in range(0, 250, 25): url = f"{base_url}?start={start}&filter=" if start > 0 else base_url print(f"正在抓取: {url}") html_content = get_page(url) if html_content: all_movies.extend(parse_page(html_content)) time.sleep(3) # 礼貌性延时 return all_movies

4. 数据存储与后续处理

获取到的数据可以保存为多种格式,这里我们展示最常用的CSV和JSON两种方式:

def save_data(movies, format='csv'): """保存电影数据""" df = pd.DataFrame(movies) if format == 'csv': df.to_csv('douban_top250.csv', index=False, encoding='utf_8_sig') elif format == 'json': df.to_json('douban_top250.json', orient='records', force_ascii=False) else: raise ValueError("不支持的格式,请选择csv或json")

调用示例:

if __name__ == '__main__': movies = crawl_top250() save_data(movies, 'csv') print(f"成功抓取{len(movies)}部电影数据!")

5. 高级技巧与异常处理

在实际爬取过程中,可能会遇到各种异常情况。以下是几个常见问题的解决方案:

反爬虫应对策略

  • 随机User-Agent:使用fake_useragent库生成随机头部
from fake_useragent import UserAgent ua = UserAgent() HEADERS['User-Agent'] = ua.random
  • IP代理池:对于大规模爬取,建议使用代理服务
PROXIES = {'http': 'http://your.proxy:port'} resp = requests.get(url, headers=HEADERS, proxies=PROXIES)

数据清洗技巧

评价人数字段原始值为"1234567人评价",我们需要提取数字部分:

votes_text = item.xpath('.//div[@class="star"]/span[last()]/text()')[0] votes = int(votes_text.replace('人评价', '').replace(',', ''))

缺失值处理

不是所有电影都有经典台词,因此需要判断:

quote = item.xpath('.//span[@class="inq"]/text()')[0] if item.xpath('.//span[@class="inq"]/text()') else None

6. 数据分析延伸应用

获取到数据后,我们可以进行各种有趣的分析:

# 读取数据 df = pd.read_csv('douban_top250.csv') # 评分分布分析 rating_dist = df['rating'].value_counts().sort_index() print("评分分布:\n", rating_dist) # 评价人数Top10 top10_voted = df.sort_values('votes', ascending=False).head(10)[['title', 'votes']] print("\n评价人数Top10:\n", top10_voted) # 评分与评价人数关系 df.plot.scatter(x='rating', y='votes', logy=True, title='评分 vs 评价人数')

通过这些分析,我们可以发现哪些电影叫好又叫座,哪些是高分小众作品等有趣现象。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/13 23:09:02

告别手动拖拽:用文本描述快速生成专业流程图的高效工具

告别手动拖拽&#xff1a;用文本描述快速生成专业流程图的高效工具 【免费下载链接】flowchart-fun Easily generate flowcharts and diagrams from text ⿻ 项目地址: https://gitcode.com/gh_mirrors/fl/flowchart-fun Flowchart Fun是一款创新的开源工具&#xff0c;…

作者头像 李华
网站建设 2026/6/13 22:59:59

RPFM:全面战争MOD开发的终极效率革命,新手也能轻松上手

RPFM&#xff1a;全面战争MOD开发的终极效率革命&#xff0c;新手也能轻松上手 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt6 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地址:…

作者头像 李华
网站建设 2026/6/13 22:58:54

神曲制造机老猫,藏在《魔力歌先生》背后的大赢家

2026年的综艺市场&#xff0c;《魔力歌先生》无疑是一匹横空出世的黑马。这档被观众戏称为“音综版喜人比赛”的节目&#xff0c;播出后在社交媒体引发了现象级讨论&#xff0c;而这场流量盛宴的背后&#xff0c;居然还有一个赢家是那个隐藏在幕后几十年的男人&#xff1a;“神…

作者头像 李华
网站建设 2026/6/13 22:58:54

Citra 3DS模拟器完全指南:在PC上免费畅玩任天堂经典游戏

Citra 3DS模拟器完全指南&#xff1a;在PC上免费畅玩任天堂经典游戏 【免费下载链接】citra A Nintendo 3DS Emulator 项目地址: https://gitcode.com/gh_mirrors/cit/citra 你是否怀念那些只能在任天堂3DS上体验的经典游戏&#xff1f;现在&#xff0c;通过Citra这款强…

作者头像 李华
网站建设 2026/6/13 22:53:58

企业级 Multi-Agent 需求调研:如何精准捕捉业务痛点与用户需求?

企业级 Multi-Agent 需求调研&#xff1a;如何精准捕捉业务痛点与用户需求&#xff1f;引言 痛点引入 各位技术负责人、产品经理、AI落地工程师&#xff0c;最近是不是被「企业级 Multi-Agent」&#xff08;多智能体系统&#xff09;这个词“轰炸”得晕头转向&#xff1f;从Ope…

作者头像 李华