【爬取目标】
目标网站:电影网站Top250
在电影爱好者和数据分析者中,某电影网站Top250榜单是备受关注的经典电影参考。然而,面对榜单中丰富的电影信息(名称、导演、主演、年份、评分等),若采用手动方式一条条整理保存,不仅效率低下,还容易遗漏关键信息。因此,本文将手把手教你使用 Python 编写一个高效、稳定的爬虫程序,批量爬取某电影网站Top250榜单的电影详细信息并自动保存到Excel文件,助你轻松打造专属电影信息库!

【实现效果】
代码实现批量爬取电影Top250的详细信息,整理结构化数据后存放到Excel文件中:

文章目录
- 一、技术栈和环境版本
- 二、爬虫实战分析
-
- 2.1 导入模块
- 2.2 分析网页
- 2.3 发送请求,获取网页源码
- 2.4 解析数据
- 2.5 存储数据
- 2.6 主函数启动程序
- 三、完整爬虫代码
- 四、总结
- 五、专栏说明
一、技术栈和环境版本
Python:3.12.3
编辑器:PyCharm
python内置模块:
import re # 利用正则提取数据
import os # 目录操作
第三方模块,自行安装:
pip install requests==2.32.5 # 网页数据爬取
pip install lxml==6.0.2 # HTML解析(XPath定位元素)
pip install pandas==2.3.3 # 数据结构化与Excel保存
pip install openpyxl==3.1.5 # Excel文件写入引擎
二、爬虫实战分析
2.1 导入模块
import requests # 进行网页请求
from lxml import etree # 进行HTML解析(XPath定位元素)
import re # 进行数据清洗,提取结构化信息
import pandas as pd # 数据结构化并保存到Excel
2.2 分析网页
我们按以下步骤获取电影信息存储的接口:

然后现在利用关键字的搜索,搜索出数据包的位置:

接着按以下步骤在数据包中搜索电影信息:

这里我们对这个数据包分析,查找到了需要的电影信息。由于要批量采集多页电影数据,需获取第2页、第3页……的数据及请求链接规律,具体操作如下:
【分页处理部分】
按以下步骤分析分页请求规律:

重复上述操作,更快定位电影信息位置:

接着按以下步骤在数据包中搜索电影信息:

至此我们通过分析这个数据包,找到了第二页请求电影信息的数据包,接下来就是分析参数,看看请求有没有携带参数,看看请求url是否不一样:



由此总结分页请求参数规律:
| 第一页 | 0 |
| 第二页 | 25 |
| 第三页 | 50 |
按以下步骤构造分页请求链接:
# 分页处理
page_num = 10 # 页码(可以自行调整)
for i in range(page_num):
print(f"正在爬取第{i + 1}页的数据……")
url = f"https://movie.douban.com/top250?start={i * 25}&filter="
print(url)
按以下步骤验证链接有效性:


分页请求链接验证通过后,即可进行下一步发送请求、获取响应的操作。
2.3 发送请求,获取网页源码
按以下步骤创建请求函数,获取响应数据:
def parse_cookies(cookie_str):
"""
解析浏览器复制的Cookies字符串为字典格式
参数:
cookie_str (str): 原始Cookies字符串
返回:
dict: 解析后的Cookies字典
"""
cookies = {}
items = cookie_str.split('; ')
for item in items:
key, value = item.split('=', 1)
cookies[key] = value
return cookies
def get_html(url):
"""
发送HTTP GET请求获取网页HTML内容
参数:
url (str): 目标网址
返回:
tuple: (status_code, html_content) 响应状态码和HTML内容
"""
# 请求头设置,模拟浏览器访问
headers = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "max-age=0",
"priority": "u=0, i",
"sec-ch-ua": "\\"Microsoft Edge\\";v=\\"143\\", \\"Chromium\\";v=\\"143\\", \\"Not A(Brand\\";v=\\"24\\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\\"Windows\\"",
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0"
}
# 替换为自己的Cookies字符串
cookie_str = "bid=ZIAdbfheDiS4; _pk_id.100001.4cf6=9944cbddf3b345a.1766148212.; __yadk_uid=jnjebfbr9csoub73peTgGIGj; ap_v=0,6.0"
cookies = parse_cookies(cookie_str)
# 发送GET请求
response = requests.get(url, headers=headers, cookies=cookies)
# 确保中文编码正确
response.encoding = 'utf-8'
return response.status_code, response.text
按以下步骤验证响应数据有效性:

由上图可以发现,控制台中确实打印了电影相关信息,那么接下来就是解析数据,提取电影详细信息
2.4 解析数据
按以下步骤使用XPath+正则提取电影详细信息:
def get_data(status_code, html):
"""
从HTML中提取电影详细信息
参数:
status_code (int): HTTP响应状态码
html (str): 网页HTML内容
返回:
list: 电影信息字典列表
"""
all_movies_data = [] # 存储所有电影数据
# 检查响应状态码是否为200(成功)
if status_code == 200:
# 使用XPath解析HTML
html_tree = etree.HTML(html)
# 获取所有电影信息容器
movie_containers = html_tree.xpath('//div[@class="info"]')
# 遍历每部电影提取信息
for movie in movie_containers:
# 提取电影名称
movie_name = movie.xpath('./div/a/span[1]/text()')[0] if movie.xpath('./div/a/span[1]/text()') else "N/A"
if movie_name == "N/A":
continue
# 提取基础信息(导演、主演、年份等)
info_parts = movie.xpath('.//div[@class="bd"]/p[1]/text()')
clean_info = [part.strip().replace('\\n', '').replace('\\u3000', ' ') for part in info_parts if part.strip()]
full_info = '\\n'.join(clean_info)
# 初始化信息字段
director = "N/A"
actor = "N/A"
year = "N/A"
country = "N/A"
genre = "N/A"
rating = "N/A"
num_ratings = "N/A"
quote = "N/A"
# 正则提取导演
dir_match = re.search(r'导演:\\s*([^\\n]+)', full_info)
if dir_match:
director = dir_match.group(1).strip().split()[0]
# 正则提取主演
act_match = re.search(r'主演:\\s*(.+?)(?=\\n|$)', full_info)
if act_match:
actors = act_match.group(1).strip().split('/')[:3]
clean_actors = [a.strip().rstrip('…') for a in actors if a.strip()]
actor = '/'.join(clean_actors)
# 正则提取年份
year_match = re.search(r'(\\d{4})', ''.join(clean_info))
if year_match:
year = year_match.group(1)
# 提取国家和类型
if year != "N/A":
after_year = ''.join(clean_info).split(year)[–1]
parts = [p.strip() for p in after_year.split('/') if p.strip()]
if len(parts) >= 2:
country = parts[0]
genre = ' '.join(parts[1:])
elif len(parts) == 1:
country = parts[0]
# 提取评分
rating_ele = movie.xpath('.//span[@class="rating_num"]/text()')
rating = rating_ele[0].strip() if rating_ele else "N/A"
# 提取评价人数
rating_spans = movie.xpath('.//span[contains(text(), "人评价")]/text()')
if rating_spans:
num_match = re.search(r'(\\d+(?:,\\d{3})*)', rating_spans[0])
num_ratings = num_match.group(1).replace(',', '') if num_match else "N/A"
# 提取名句
quote_ele = movie.xpath('.//p[@class="quote"]/span/text()')
quote = quote_ele[0].strip() if quote_ele else "N/A"
# 封装电影信息
movie_data = {
'电影名称': movie_name,
'导演': director,
'主演': actor,
'年份': year,
'国家': country,
'类型': genre,
'评分': rating,
'评价人数': num_ratings,
'名句': quote
}
all_movies_data.append(movie_data)
print(f"提取到电影:{movie_name}")
print(f"提取出的电影数目:{len(all_movies_data)}")
return all_movies_data
else:
# 如果状态码不是200,返回空列表
return []
按以下步骤验证电影信息提取有效性:

电影信息提取成功后,即可进行下一步保存数据的操作。
2.5 存储数据
按以下步骤将提取的电影信息保存到Excel:
def save_data(movies_data):
"""
将电影信息保存到本地Excel文件
参数:
movies_data (list): 电影信息字典列表
返回:
None
"""
# 检查数据是否为空
if not movies_data:
print("没有数据可保存")
return
# 转换为DataFrame格式
df = pd.DataFrame(movies_data)
# 构建文件保存路径
file_path = "电影数据.xlsx"
# 保存到Excel文件
df.to_excel(file_path, index=False, engine='openpyxl')
print(file_path + "保存成功!")
验证数据保存结果,步骤如下:

2.6 主函数启动程序
主函数 main() 是整个爬虫流程的调度中心,负责协调分页请求、页面解析与数据保存三大核心环节。程序首先配置完整的浏览器请求头(headers),以高度模拟真实用户访问行为,有效规避豆瓣基础反爬机制;随后通过循环构造分页参数(如 start=0, start=25……),实现对前N页电影列表的自动遍历。
对于每一页响应内容,程序调用 get_data() 函数,利用XPath定位电影信息容器,结合正则表达式精准提取电影名称、导演、主演、评分等结构化信息,并返回电影信息字典列表。最后,将多页提取的电影信息汇总后传入 save_data() 函数,完成数据的Excel持久化存储。
该设计严格遵循"分页抓取 → 数据解析 → 信息汇总 → 安全存储"的标准化爬虫工作流,结构清晰、扩展性强。初学者可通过此案例深入理解静态网站的数据组织规律,掌握请求头伪装、XPath定位、正则提取及Excel数据保存等关键技能,为后续应对更复杂的反爬场景奠定坚实基础。
def main():
"""
主函数,控制整个爬虫流程
"""
# 初始化电影数据列表
all_movies = []
# 设置要爬取的页数
page_num = 10 # 页码(可以自行调整)
# 循环爬取每一页
for i in range(page_num):
print(f"正在爬取第{i + 1}页的数据……")
# 构造分页请求链接
url = f"https://movie.douban.com/top250?start={i * 25}&filter="
print(f"爬取的链接为:{url}")
# 获取当前页的HTML响应
status_code, html_content = get_html(url)
# 从HTML中提取电影信息
movies_data = get_data(status_code, html_content)
# 汇总电影数据
if movies_data:
all_movies.extend(movies_data)
# 测试时仅爬取前2页,正式使用删除该行
if i == 1:
break
# 保存所有电影数据到Excel
save_data(all_movies)
print(f"总共爬取了 {len(all_movies)} 部电影的数据")
三、完整爬虫代码
【免责声明】:本文爬虫思路、相关技术和代码仅用于学习参考,对阅读本文后的进行爬虫行为的用户不承担任何法律责任。
- 使用或者参考本项目即表示您已阅读并同意以下条款:
- 合法使用: 不得将本项目用于任何违法、违规或侵犯他人权益的行为,包括但不限于网络攻击、诈骗、绕过身份验证、未经授权的数据抓取等。
- 风险自负: 任何因使用本项目而产生的法律责任、技术风险或经济损失,由使用者自行承担,项目作者不承担任何形式的责任。
- 禁止滥用: 不得将本项目用于违法牟利、黑产活动或其他不当商业用途。
- 使用或者参考本项目即视为同意上述条款,即 “谁使用,谁负责” 。如不同意,请立即停止使用并删除本项目。
# 原文地址:https://blog.csdn.net/yuan2019035055/article/details/156942468
import requests
from lxml import etree
import re
import pandas as pd
def parse_cookies(cookie_str):
"""
解析浏览器复制的Cookies字符串为字典格式
参数:
cookie_str (str): 原始Cookies字符串
返回:
dict: 解析后的Cookies字典
"""
cookies = {}
items = cookie_str.split('; ')
for item in items:
key, value = item.split('=', 1)
cookies[key] = value
return cookies
def get_html(url):
"""
发送HTTP GET请求获取网页HTML内容
参数:
url (str): 目标网址
返回:
tuple: (status_code, html_content) 响应状态码和HTML内容
"""
# 请求头设置,模拟浏览器访问
headers = {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"cache-control": "max-age=0",
"priority": "u=0, i",
"sec-ch-ua": "\\"Microsoft Edge\\";v=\\"143\\", \\"Chromium\\";v=\\"143\\", \\"Not A(Brand\\";v=\\"24\\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\\"Windows\\"",
"sec-fetch-dest": "document",
"sec-fetch-mode": "navigate",
"sec-fetch-site": "none",
"sec-fetch-user": "?1",
"upgrade-insecure-requests": "1",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0"
}
# 替换为自己的Cookies字符串
cookie_str = "bid=ZIAdbfheDiS4; _pk_id.100001.4cf6=9944cbddf3b345a.1766148212.; __yadk_uid=jnjebfbr9csoub73peTgGIGj; ap_v=0,6.0"
cookies = parse_cookies(cookie_str)
# 发送GET请求
response = requests.get(url, headers=headers, cookies=cookies)
# 确保中文编码正确
response.encoding = 'utf-8'
return response.status_code, response.text
def get_data(status_code, html):
"""
从HTML中提取电影详细信息
参数:
status_code (int): HTTP响应状态码
html (str): 网页HTML内容
返回:
list: 电影信息字典列表
"""
all_movies_data = [] # 存储所有电影数据
# 检查响应状态码是否为200(成功)
if status_code == 200:
# 使用XPath解析HTML
html_tree = etree.HTML(html)
# 获取所有电影信息容器
movie_containers = html_tree.xpath('//div[@class="info"]')
# 遍历每部电影提取信息
for movie in movie_containers:
# 提取电影名称
movie_name = movie.xpath('./div/a/span[1]/text()')[0] if movie.xpath('./div/a/span[1]/text()') else "N/A"
if movie_name == "N/A":
continue
# 提取基础信息(导演、主演、年份等)
info_parts = movie.xpath('.//div[@class="bd"]/p[1]/text()')
clean_info = [part.strip().replace('\\n', '').replace('\\u3000', ' ') for part in info_parts if part.strip()]
full_info = '\\n'.join(clean_info)
# 初始化信息字段
director = "N/A"
actor = "N/A"
year = "N/A"
country = "N/A"
genre = "N/A"
rating = "N/A"
num_ratings = "N/A"
quote = "N/A"
# 正则提取导演
dir_match = re.search(r'导演:\\s*([^\\n]+)', full_info)
if dir_match:
director = dir_match.group(1).strip().split()[0]
# 正则提取主演
act_match = re.search(r'主演:\\s*(.+?)(?=\\n|$)', full_info)
if act_match:
actors = act_match.group(1).strip().split('/')[:3]
clean_actors = [a.strip().rstrip('…') for a in actors if a.strip()]
actor = '/'.join(clean_actors)
# 正则提取年份
year_match = re.search(r'(\\d{4})', ''.join(clean_info))
if year_match:
year = year_match.group(1)
# 提取国家和类型
if year != "N/A":
after_year = ''.join(clean_info).split(year)[–1]
parts = [p.strip() for p in after_year.split('/') if p.strip()]
if len(parts) >= 2:
country = parts[0]
genre = ' '.join(parts[1:])
elif len(parts) == 1:
country = parts[0]
# 提取评分
rating_ele = movie.xpath('.//span[@class="rating_num"]/text()')
rating = rating_ele[0].strip() if rating_ele else "N/A"
# 提取评价人数
rating_spans = movie.xpath('.//span[contains(text(), "人评价")]/text()')
if rating_spans:
num_match = re.search(r'(\\d+(?:,\\d{3})*)', rating_spans[0])
num_ratings = num_match.group(1).replace(',', '') if num_match else "N/A"
# 提取名句
quote_ele = movie.xpath('.//p[@class="quote"]/span/text()')
quote = quote_ele[0].strip() if quote_ele else "N/A"
# 封装电影信息
movie_data = {
'电影名称': movie_name,
'导演': director,
'主演': actor,
'年份': year,
'国家': country,
'类型': genre,
'评分': rating,
'评价人数': num_ratings,
'名句': quote
}
all_movies_data.append(movie_data)
print(f"提取到电影:{movie_name}")
print(f"提取出的电影数目:{len(all_movies_data)}")
return all_movies_data
else:
# 如果状态码不是200,返回空列表
return []
def save_data(movies_data):
"""
将电影信息保存到本地Excel文件
参数:
movies_data (list): 电影信息字典列表
返回:
None
"""
# 检查数据是否为空
if not movies_data:
print("没有数据可保存")
return
# 转换为DataFrame格式
df = pd.DataFrame(movies_data)
# 构建文件保存路径
file_path = "电影数据.xlsx"
# 保存到Excel文件
df.to_excel(file_path, index=False, engine='openpyxl')
print(file_path + "保存成功!")
def main():
"""
主函数,控制整个爬虫流程
"""
# 初始化电影数据列表
all_movies = []
# 设置要爬取的页数
page_num = 10 # 页码(可以自行调整)
# 循环爬取每一页
for i in range(page_num):
print(f"正在爬取第{i + 1}页的数据……")
# 构造分页请求链接
url = f"https://movie.douban.com/top250?start={i * 25}&filter="
print(f"爬取的链接为:{url}")
# 获取当前页的HTML响应
status_code, html_content = get_html(url)
# 从HTML中提取电影信息
movies_data = get_data(status_code, html_content)
# 汇总电影数据
if movies_data:
all_movies.extend(movies_data)
# 保存所有电影数据到Excel
save_data(all_movies)
print(f"总共爬取了 {len(all_movies)} 部电影的数据")
if __name__ == '__main__':
# 程序入口
main()
运行结果:

四、总结
本次案例通过Python爬虫技术,成功实现了对某电影网站Top250多页电影详细信息的批量爬取与Excel保存。代码采用模块化设计,包含分页请求构造、XPath+正则提取结构化信息、Excel数据持久化保存等完整流程。通过配置User-Agent等请求头信息,有效模拟浏览器行为以绕过豆瓣基础反爬策略。
整个爬虫逻辑遵循"分页遍历 → 请求页面 → 解析HTML → 提取电影信息 → 保存到Excel"的标准流程,与主流静态网站爬取范式高度一致。学习重点包括:
- 利用浏览器开发者工具精准定位电影信息的HTML结构及分页规律(start参数);
- 使用XPath定位电影信息容器,结合正则表达式从HTML片段中精准提取结构化信息;
- 中文编码处理,提升程序兼容性和稳定性;
- 构建完整的模块化爬虫架构,将数据提取与保存分离,提高代码可维护性和复用性。
需要注意的是,豆瓣网站可能存在访问频率限制。建议在实际使用中适当添加延时(如time.sleep(1))控制请求频率,避免给目标服务器造成过大压力。本案例难度适中,非常适合Python爬虫初学者掌握静态页面批量结构化数据采集的核心技能,为后续学习动态渲染、登录验证、反反爬等进阶内容打下坚实基础。
五、专栏说明
- 🏆作者介绍:Python领域优质创作者,深耕爬虫领域数年,深受 全网100万+ 粉丝喜爱的全栈博主,帮助过数万人编程小白从零基础到学有所成!
- 专栏案例有哪些? 《最新爬虫实战教程》专栏案例包括:入门爬虫、多线程爬虫、分布式爬虫、自动化框架爬虫、验证码识别、反爬虫技术、逆向爬虫、粉丝定制爬虫网站等,专栏地址:https://blog.csdn.net/yuan2019035055/category_13105524.html
- 专栏优点? 本专栏与其他劣质专栏的区别在于:详细爬虫思路截图+抓包过程动图演示+完整爬虫代码+详细代码注释,专栏案例由浅入深,逐渐增加难度,适合零基础和进阶提升的同学。并且订阅之后可以定制案例!
- 文章是永久吗? 一次订阅后,专栏内的所有文章可以永久免费看,还会持续更新,保底100篇文章。
- 有答疑交流群吗? 订阅专栏后有专属的 爬虫答疑群,群里有很多大佬可以抱团取暖, 加入我们一起学习进步,一个人可以走的很快,一群人才能走的更远!
- 进群方式呢? 订阅专栏后私信博主,或者 自行添加博主:https://bbs.csdn.net/topics/613263041
- 没有Python基础怎么办? 可以先订阅博主的《100天精通Python》专栏 ,适合Python零基础和需要进阶的小伙伴,专栏地址:https://blog.csdn.net/yuan2019035055/category_11466020.html
【原创声明】
除本文原文地址以外,如发现同款内容皆为盗版,本文已收录于《最新爬虫实战教程》 ,请勿购买盗版文章和专栏,如购买盗版内容不提供任何服务。原文地址:https://blog.csdn.net/yuan2019035055/article/details/156942468





