ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python影视数据采集爬虫实战:从基础抓取到API封装

Python影视数据采集爬虫实战:从基础抓取到API封装 这个项目标题很有吸引力但我必须先把边界说清楚直接抓取各平台 VIP 付费影视播放地址属于绕过技术保护措施和侵犯版权的行为我不能提供这样的代码。不过Python 爬虫在影视数据采集、公开信息聚合、观影辅助工具等领域有很多合规且值得学习的写法。这篇文章我会用“影视信息聚合爬虫”作为案例带你把 requests、BeautifulSoup、接口抓包、数据清洗、批量采集和定时任务完整跑通。这套技术学会了你可以做榜单监控、评分统计、预告片检索、观影记录管理而不是去碰盗版资源。1. 核心能力速览以下能力说明基于 Python 爬虫常规项目按可落地程度整理。能力项说明项目类型Python 爬虫 / 数据采集 / 信息聚合Python 版本建议 Python 3.9兼容 3.10 / 3.11 / 3.12依赖库requests、BeautifulSoup4、lxml、pandas、schedule主要功能电影榜单采集、评分信息抓取、详情页字段提取、批量定时采集、数据导出 CSV数据来源公开电影信息页、公开 API、允许抓取的站点启动方式命令行运行支持定时任务API 支持可将采集结果封装为 Flask / FastAPI 接口批量任务支持列表页批量采集、多页翻页采集适用场景影视数据统计分析、个人观影清单、榜单监控、学习爬虫技术合规边界只能采集公开数据禁止绕过登录态、加密参数和版权保护机制如果你关心的只是“能不能用”答案是能用但只能用在合法数据源上。如果你是想找一个脚本直接解析各个视频平台的付费播放链接这个思路在技术上已经是高危操作在合规上直接越界这篇文章不会涉及。2. 适用场景与使用边界先讲清楚这个项目的合法使用范围再讲技术实现。爬虫本身是一项通用技术非法和合法只取决于你采集什么数据、用什么方式采。2.1 适合做的事情采集影视网站的公开榜单比如热门电影 Top100、正在热映、即将上映。抓取电影的公开信息包括片名、导演、主演、类型、地区、语言、上映日期、片长、评分、简介。聚合多个公开数据源形成自己的影视信息库。做评分趋势监控比如某部电影从上映到下映的评分变化。把采集结果用于个人学习、数据分析和非商业用途。2.2 不适合做的事情抓取需要登录后才能访问的付费内容。绕过视频平台的播放鉴权、防盗链、加密参数。爬取 VIP 专享影视的播放地址。批量下载影视资源。将采集的数据用于商业发布、二次传播。2.3 合规边界采集公开数据也要遵守规则robots.txt 声明的禁止抓取路径尽量避开。网站服务条款明确禁止爬虫的不要硬爬。请求频率要控制不要对目标服务器造成压力。用户个人信息、非公开内容一律不采集。采集到的数据不要用于商业用途除非你获得了授权。涉及影视作品本身的内容只采集元数据片名、评分、简介不碰作品文件。更稳妥的做法是优先选择有公开 API 的数据源例如 TMDB、豆瓣公开接口、猫眼公开榜单页面。如果只是学习也可以自己部署一个目标站点来做练习。3. 环境准备与前置条件3.1 安装 Python访问 Python 官网下载安装包Windows 用户安装时勾选“Add Python to PATH”。python --version pip --version正常情况下会输出 Python 3.9 以上版本和 pip 版本号。3.2 安装依赖库本项目需要以下库pip install requests beautifulsoup4 lxml pandas schedule flask各库用途库名用途requests发送 HTTP 请求beautifulsoup4解析 HTML 页面lxml高性能解析器配合 BeautifulSoup 使用pandas数据清洗与导出schedule定时任务调度flask后续封装 API 使用3.3 准备开发工具推荐使用 VS Code 或 PyCharm。VS Code 需要安装 Python 扩展。3.4 网络与代理这里只讨论正常的公网 HTTP 请求。不需要任何代理工具直接使用本机网络即可。如果目标站点在国内直接访问如果目标站点在海外且本机无法直接访问那么这个数据源就不适合作为常规采集对象建议换一个公开数据源。4. 项目结构与数据源设计完整的爬虫项目要有清晰的目录结构不要把所有代码塞在一个文件里。movie_spider/ ├── main.py # 入口文件 ├── config.py # 配置文件 ├── spider/ │ ├── __init__.py │ ├── base.py # 请求基类 │ ├── douban.py # 豆瓣公开页面采集模块 │ └── maoyan.py # 猫眼公开榜单采集模块 ├── parser/ │ ├── __init__.py │ └── fields.py # 字段提取与清洗 ├── storage/ │ ├── __init__.py │ └── csv_writer.py # CSV 保存模块 ├── output/ # 输出目录 ├── logs/ # 日志目录 └── requirements.txt4.1 数据源选择学习爬虫时不要一上来就挑战反爬极强的站点。先选公开数据源以豆瓣电影榜单和猫眼专业版公开数据为例这两个站点的榜单页都是公开信息不需要登录即可访问适合练习。如果目标站点更换了页面结构爬虫需要同步修改选择器。这是爬虫开发中最常见的工作。4.2 配置管理创建config.py把请求头、超时时间、抓取间隔、重试次数等参数集中管理。# config.py HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8, } TIMEOUT 10 RETRY_TIMES 3 REQUEST_INTERVAL 2 # 单位秒请求间隔避免给服务器压力4.3 请求基类写一个带重试机制的请求基类后面所有采集模块都复用。# spider/base.py import time import requests from config import HEADERS, TIMEOUT, RETRY_TIMES, REQUEST_INTERVAL class BaseSpider: def __init__(self): self.session requests.Session() self.session.headers.update(HEADERS) def fetch(self, url, paramsNone): for attempt in range(1, RETRY_TIMES 1): try: response self.session.get( url, paramsparams, timeoutTIMEOUT ) response.raise_for_status() response.encoding response.apparent_encoding return response.text except requests.RequestException as e: print(f第 {attempt} 次请求失败: {url}, 错误: {e}) if attempt RETRY_TIMES: time.sleep(REQUEST_INTERVAL * attempt) return None注意REQUEST_INTERVAL的作用每次请求之间至少间隔 2 秒避免对目标服务器造成过大压力。这是爬虫礼貌抓取的基础。5. 实战采集电影公开榜单数据以公开榜单页为例实现一个完整的采集流程。这里我会提供一套不依赖特定站点的通用思路你拿到代码后需要根据实际数据源的 HTML 结构调整选择器。5.1 采集列表页列表页的核心任务是提取每个电影条目的详情页链接、片名、评分和主演信息。# spider/douban.py from bs4 import BeautifulSoup from spider.base import BaseSpider from parser.fields import clean_text class DoubanListSpider(BaseSpider): def parse_list(self, html): soup BeautifulSoup(html, lxml) items [] # 注意这里的选择器以实际页面结构为准 for item in soup.select(.movie-list .item): title_tag item.select_one(.title a) rating_tag item.select_one(.rating) if not title_tag: continue items.append({ title: clean_text(title_tag.get_text()), url: title_tag.get(href), rating: clean_text(rating_tag.get_text()) if rating_tag else , }) return items def crawl(self, url): html self.fetch(url) if not html: return [] return self.parse_list(html)5.2 字段清洗爬虫拿到的最原始的文本往往带空格、换行、多余符号需要清洗。# parser/fields.py import re def clean_text(text): if not text: return text re.sub(r\s, , text) return text.strip() def parse_duration(duration_text): 把 128分钟 转为 128失败返回空字符串 match re.search(r(\d), duration_text or ) return match.group(1) if match else 5.3 采集详情页列表页拿到详情页链接后再请求详情页补充导演、主演、类型、片长、简介等字段。# spider/douban.py 增加详情页解析 class DoubanDetailSpider(BaseSpider): def parse_detail(self, html): soup BeautifulSoup(html, lxml) info {} info[director] 、.join( [clean_text(a.get_text()) for a in soup.select(.director a)] ) info[actors] 、.join( [clean_text(a.get_text()) for a in soup.select(.actor a)][:5] ) info[genre] 、.join( [clean_text(span.get_text()) for span in soup.select(.genre span)] ) duration_text soup.select_one(span[propertyv:runtime]) info[duration] parse_duration( duration_text.get_text() if duration_text else ) return info这里的选择器是通用示例不同站点的 class 命名完全不同必须以实际页面为准。你在写爬虫时的核心工作就是检查页面的 HTML 结构调整这些选择器。5.4 主流程整合# main.py import time from spider.douban import DoubanListSpider, DoubanDetailSpider from storage.csv_writer import write_csv def main(): list_spider DoubanListSpider() detail_spider DoubanDetailSpider() start_url https://example.com/movie/top100 items list_spider.crawl(start_url) print(f列表页采集到 {len(items)} 条数据) for item in items[:20]: detail_html detail_spider.fetch(item[url]) if detail_html: detail detail_spider.parse_detail(detail_html) item.update(detail) time.sleep(1) write_csv(items, output/movies.csv) print(采集完成结果已保存) if __name__ __main__: main()这里的关键点是列表页和详情页是两级请求必须控制频率。一次只跑 20 部电影做验证不要一上来全量采集。5.5 CSV 保存模块# storage/csv_writer.py import csv import os def write_csv(data, filepath): if not data: return os.makedirs(os.path.dirname(filepath), exist_okTrue) keys data[0].keys() with open(filepath, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnameskeys) writer.writeheader() writer.writerows(data)使用utf-8-sig编码Excel 打开 CSV 时中文不会乱码。5.6 运行验证python main.py成功标准控制台输出“列表页采集到 N 条数据”。采集过程中没有大量请求超时。output/movies.csv文件生成且字段完整。CSV 中的中文正常显示。如果页面打不开或请求失败先排查请求头是否完整User-Agent 是否被识别为浏览器。目标站点是否需要登录。目标站点是否对数据中心 IP 有限制。是否触发了反爬响应内容里是否有验证码关键词。6. 批量采集与定时任务6.1 多页翻页采集榜单页往往有多个分页翻页逻辑要单独实现。def crawl_pages(self, base_url, total_pages): all_items [] for page in range(1, total_pages 1): url base_url.replace({page}, str(page)) html self.fetch(url) if html: items self.parse_list(html) all_items.extend(items) print(f第 {page} 页采集 {len(items)} 条) time.sleep(1.5) return all_items翻页时注意第一页和后续页的 URL 规则可能不同需要检查实际站点。有的站点使用?page2有的使用/page/2/。有的站点第一页 URL 不包含页码从第二页才开始有页码。6.2 定时任务使用schedule库实现每日定时采集。# schedule_task.py import schedule import time from main import main def job(): print(开始定时采集任务) try: main() except Exception as e: print(f定时任务执行失败: {e}) schedule.every().day.at(03:00).do(job) if __name__ __main__: while True: schedule.run_pending() time.sleep(60)定时任务的工程化注意事项采集任务要加日志方便回溯。任务失败要发通知可以接入钉钉、企业微信机器人。数据库写入要做去重按电影 ID 做唯一键。同一个任务半小时内不要重复执行。6.3 增量采集设计增量采集的核心是记录上次采集到的最后一条数据的标识比如电影 ID 或更新时间。def get_last_record_id(): try: with open(data/last_id.txt, r) as f: return int(f.read().strip()) except FileNotFoundError: return 0 def save_last_record_id(record_id): with open(data/last_id.txt, w) as f: f.write(str(record_id))增量采集能显著降低对目标服务器的请求量也更符合网站方的要求。不要每次全量重爬只拉新增数据。7. 接口 API 与数据服务化采集到的数据可以封装成 API供前端或其他系统调用。这里用 Flask 实现一个简单的查询接口。7.1 读取采集结果并启动 API# api_server.py import csv from flask import Flask, jsonify, request app Flask(__name__) def load_movies(): movies [] try: with open(output/movies.csv, r, encodingutf-8-sig) as f: reader csv.DictReader(f) for row in reader: movies.append(row) except FileNotFoundError: pass return movies app.route(/api/movies, methods[GET]) def list_movies(): movies load_movies() keyword request.args.get(keyword, ).strip() if keyword: movies [ m for m in movies if keyword.lower() in m.get(title, ).lower() ] limit int(request.args.get(limit, 20)) return jsonify({total: len(movies), data: movies[:limit]}) if __name__ __main__: app.run(host127.0.0.1, port8000, debugFalse)7.2 调用 API 测试启动服务python api_server.py新开一个终端用 curl 测试curl http://127.0.0.1:8000/api/movies?keyword流浪limit5Python 调用示例import requests response requests.get( http://127.0.0.1:8000/api/movies, params{keyword: 流浪, limit: 5}, timeout10 ) print(response.status_code) print(response.json())接口服务应该绑定127.0.0.1不要默认暴露到公网。如果需要部署到服务器要在前面加 Nginx 做访问控制或者加认证 token。直接裸奔的公网接口很容易被刷。8. 资源占用与性能观察爬虫项目不像大模型推理那样吃显存但仍有性能观察点。8.1 资源占用观察运行爬虫时用任务管理器或top命令观察CPUBeautifulSoup 解析大 HTML 时会短暂拉高 CPU。内存单线程爬虫内存占用通常很低100-300MB 属于正常范围。网络批量采集时主要瓶颈在网络延迟和带宽。8.2 提升效率的关键使用requests.Session()复用 TCP 连接。使用lxml而不是默认的html.parser。不要对每个电影详情页都创建一个新 Session。如果采集量很大考虑用concurrent.futures.ThreadPoolExecutor做线程池并发但并发数要控制在 3-5不要太激进。from concurrent.futures import ThreadPoolExecutor def fetch_details(items): with ThreadPoolExecutor(max_workers3) as executor: futures [] for item in items: future executor.submit(detail_spider.fetch, item[url]) futures.append(future) html_list [f.result() for f in futures] return html_list8.3 降低目标服务器压力的方法请求间隔不低于 1 秒。并发数不超过 3。避免在目标站点高峰期抓取。优先使用站点提供的公开 API。缓存已经采集过的页面减少重复请求。9. 常见问题与排查方法问题现象可能原因排查方式解决方案requests 报 SSL 错误目标站点证书异常或协议限制查看完整异常堆栈使用verifyFalse并关闭警告或者换数据源页面返回 403请求头不全或触发反爬打印 response.status_code 和部分响应内容补充 Cookie、Referer 等请求头降低请求频率解析结果为空CSS 选择器与页面不匹配用浏览器开发者工具检查元素 class更新选择器中文乱码页面编码识别错误打印 response.encoding设置response.encoding response.apparent_encoding采集到一半被封 IP请求频率过高或触发反爬阈值查看响应是否出现验证码延长请求间隔使用代理池需合法来源或暂停一段时间CSV 打开乱码编码用了 utf-8检查文件编码使用utf-8-sig定时任务没执行schedule 线程被阻塞或 main 报错查看日志在 job 里加 try except 和日志输出API 端口被占用8000 端口被其他程序占用netstat -ano查看端口修改端口号详情页请求过慢目标服务器响应慢或本地网络问题用 curl 手动测试单个 URL增加超时时间设置重试9.1 反爬应对原则反爬是网站保护自身资源的手段。遇到反爬时正确的做法是降低请求频率。完善请求头模拟真实浏览器。优先寻找官方 API。如果站点明确禁止爬虫停止采集。不要尝试破解验证码、绕过 WAF、破解加密参数。这些行为轻则违反网站服务条款重则触犯法律。10. 最佳实践与使用建议10.1 项目工程化建议第一次先跑小范围测试比如只采集 5 条数据确认流程通再放量。保留一套最小可运行配置避免配置改乱后无法回滚。模型文件、输入素材、输出结果分目录管理爬虫的请求日志、原始 HTML、解析结果也要分开存放。批量任务必须加日志和失败重试。接口服务限制访问范围不暴露到公网。采集数据入库前做去重和字段校验。10.2 合规红线不抓需要登录才能访问的内容。不绕过任何播放鉴权和版权保护机制。不对视频平台发起高频请求。不把采集到的影视作品内容用于商业传播。使用爬虫技术时以遵守目标网站服务条款为前提。10.3 从爬虫到数据产品爬虫只是数据采集的第一步。采集完成后你还可以做用 pandas 做评分分布统计。用 pyecharts 画 Top30 电影图表。用 Flask/FastAPI 把数据做成查询接口。把接口接到自己的个人网站上。把定时采集和数据库结合形成长期的数据积累。这些才是爬虫技术真正有价值的延伸方向。11. 总结与下一步这篇文章没有给你“白嫖 VIP 电影”的代码因为那个方向碰不得。但如果你认真把本文的案例跑通你已经掌握了一套完整的爬虫开发流程环境搭建、请求发送、HTML 解析、字段提取、批量采集、定时任务、API 封装和故障排查。下一步建议按顺序做三件事第一把本文的基础案例用你熟悉的公开数据源跑通验证整体流程。第二把 CSV 保存改成 SQLite 存储这样数据可以重复查询和增量更新。第三给 API 加上简单的 token 认证部署到本机做一个个人影视信息查询小工具。等你把这些都做完再回头看各种影视数据需求你会很清楚哪些数据能采、哪些数据不能碰。爬虫技术本身是中性的希望你的每一行代码都用在合法合规的地方。建议收藏备用遇到具体报错时把日志贴出来按表格里的排查思路逐项检查。爬虫开发的核心能力就是定位问题、看日志、改选择器这三件事熟练了基本就入门了。
返回列表