当前位置: 首页 > article >正文

Python实例题: Python 的简单电影信息

目录

Python实例题

题目

代码实现

实现原理

网页请求:

内容解析:

数据存储:

反爬策略:

关键代码解析

1. 网页请求处理

2. 电影列表解析

3. 电影详情解析

4. 爬虫主逻辑

使用说明

安装依赖:

修改配置:

运行爬虫:

查看结果:

注意事项

法律合规:

反爬策略:

网站结构变化:

数据使用限制:

Python实例题

题目

 Python 的简单电影信息

代码实现

import requests
from bs4 import BeautifulSoup
import json
import time
import random
import logging
from fake_useragent import UserAgentclass MovieCrawler:"""电影信息爬虫类"""def __init__(self):"""初始化爬虫"""self.ua = UserAgent()self.headers = {'User-Agent': self.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.8,en;q=0.6','Connection': 'keep-alive'}self.logger = self._setup_logger()self.movies = []def _setup_logger(self):"""配置日志记录"""logger = logging.getLogger('movie_crawler')logger.setLevel(logging.INFO)# 创建控制台处理器ch = logging.StreamHandler()ch.setLevel(logging.INFO)# 创建日志格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')ch.setFormatter(formatter)# 添加处理器到loggerlogger.addHandler(ch)return loggerdef fetch_movie_list(self, url, page_num=1):"""获取电影列表页Args:url: 电影列表页URLpage_num: 页码Returns:页面内容或None"""try:# 构造完整URLfull_url = f"{url}?page={page_num}" if page_num > 1 else url# 更新User-Agentself.headers['User-Agent'] = self.ua.random# 发送请求response = requests.get(full_url, headers=self.headers, timeout=10)# 检查响应状态if response.status_code == 200:self.logger.info(f"成功获取页面: {full_url}")return response.textelse:self.logger.error(f"获取页面失败,状态码: {response.status_code}, URL: {full_url}")return Noneexcept Exception as e:self.logger.error(f"请求发生异常: {str(e)}")return Nonedef parse_movie_list(self, html_content):"""解析电影列表页Args:html_content: 页面HTML内容Returns:电影信息列表"""if not html_content:return []try:soup = BeautifulSoup(html_content, 'html.parser')movie_items = []# 这里需要根据实际网站结构调整选择器# 以下是一个示例选择器,用于演示目的for item in soup.select('.movie-item'):try:title = item.select_one('.title').text.strip()link = item.select_one('a')['href']rating = item.select_one('.rating').text.strip()year = item.select_one('.year').text.strip()movie_items.append({'title': title,'link': link,'rating': rating,'year': year})except (AttributeError, KeyError) as e:self.logger.warning(f"解析电影项时出错: {str(e)}")continueself.logger.info(f"成功解析 {len(movie_items)} 部电影")return movie_itemsexcept Exception as e:self.logger.error(f"解析页面时发生异常: {str(e)}")return []def fetch_movie_detail(self, url):"""获取电影详情页Args:url: 电影详情页URLReturns:页面内容或None"""try:# 更新User-Agentself.headers['User-Agent'] = self.ua.random# 发送请求response = requests.get(url, headers=self.headers, timeout=15)# 检查响应状态if response.status_code == 200:self.logger.info(f"成功获取详情页: {url}")return response.textelse:self.logger.error(f"获取详情页失败,状态码: {response.status_code}, URL: {url}")return Noneexcept Exception as e:self.logger.error(f"请求详情页发生异常: {str(e)}")return Nonedef parse_movie_detail(self, html_content, base_info):"""解析电影详情页Args:html_content: 页面HTML内容base_info: 从列表页获取的基础信息Returns:完整的电影信息"""if not html_content:return base_infotry:soup = BeautifulSoup(html_content, 'html.parser')# 提取详细信息,这里需要根据实际网站结构调整选择器director = soup.select_one('.director').text.strip() if soup.select_one('.director') else '未知'actors = [a.text.strip() for a in soup.select('.actors li')] if soup.select('.actors li') else []genre = [g.text.strip() for g in soup.select('.genre a')] if soup.select('.genre a') else []duration = soup.select_one('.duration').text.strip() if soup.select_one('.duration') else '未知'description = soup.select_one('.description').text.strip() if soup.select_one('.description') else ''# 合并信息movie_info = {**base_info,'director': director,'actors': actors,'genre': genre,'duration': duration,'description': description}return movie_infoexcept Exception as e:self.logger.error(f"解析详情页时发生异常: {str(e)}")return base_infodef crawl(self, base_url, total_pages=1):"""执行爬虫Args:base_url: 电影列表页基础URLtotal_pages: 要爬取的总页数"""self.logger.info(f"开始爬取电影信息,总页数: {total_pages}")for page in range(1, total_pages + 1):self.logger.info(f"正在爬取第 {page} 页...")# 获取电影列表页list_content = self.fetch_movie_list(base_url, page)# 解析电影列表movie_list = self.parse_movie_list(list_content)# 遍历电影列表,获取详情for movie in movie_list:# 构造完整详情页URLdetail_url = movie['link']if not detail_url.startswith('http'):detail_url = base_url + detail_url# 获取电影详情页detail_content = self.fetch_movie_detail(detail_url)# 解析电影详情full_movie_info = self.parse_movie_detail(detail_content, movie)# 添加到结果列表self.movies.append(full_movie_info)self.logger.info(f"成功获取电影: {full_movie_info['title']}")# 随机延时,避免过快请求time.sleep(random.uniform(1, 3))# 页面间延时time.sleep(random.uniform(2, 5))self.logger.info(f"爬取完成,共获取 {len(self.movies)} 部电影信息")def save_to_json(self, filename='movies.json'):"""将爬取的电影信息保存到JSON文件Args:filename: 保存的文件名"""try:with open(filename, 'w', encoding='utf-8') as f:json.dump(self.movies, f, ensure_ascii=False, indent=2)self.logger.info(f"电影信息已保存到 {filename}")except Exception as e:self.logger.error(f"保存文件时发生异常: {str(e)}")# 示例使用
def example_usage():# 注意:这只是一个示例URL,实际上需要替换为真实的电影网站URLbase_url = "https://example.com/movies"# 创建爬虫实例crawler = MovieCrawler()# 执行爬虫,爬取前3页crawler.crawl(base_url, total_pages=3)# 保存结果crawler.save_to_json('movies.json')if __name__ == "__main__":example_usage()    

实现原理

这个简单的电影爬虫基于以下技术实现:

  • 网页请求

    • 使用 requests 库发送 HTTP 请求
    • 随机更换 User-Agent 模拟不同浏览器
    • 设置合理的请求间隔避免被封 IP
  • 内容解析

    • 使用 BeautifulSoup 解析 HTML 内容
    • 通过 CSS 选择器提取所需信息
    • 处理可能的解析异常
  • 数据存储

    • 将爬取的电影信息存储为 JSON 格式
    • 提供清晰的日志记录功能
  • 反爬策略

    • 随机延时请求
    • 动态更换请求头
    • 异常处理和日志记录

关键代码解析

1. 网页请求处理

def fetch_movie_list(self, url, page_num=1):try:full_url = f"{url}?page={page_num}" if page_num > 1 else urlself.headers['User-Agent'] = self.ua.randomresponse = requests.get(full_url, headers=self.headers, timeout=10)if response.status_code == 200:self.logger.info(f"成功获取页面: {full_url}")return response.textelse:self.logger.error(f"获取页面失败,状态码: {response.status_code}, URL: {full_url}")return Noneexcept Exception as e:self.logger.error(f"请求发生异常: {str(e)}")return None

2. 电影列表解析

def parse_movie_list(self, html_content):if not html_content:return []try:soup = BeautifulSoup(html_content, 'html.parser')movie_items = []for item in soup.select('.movie-item'):try:title = item.select_one('.title').text.strip()link = item.select_one('a')['href']rating = item.select_one('.rating').text.strip()year = item.select_one('.year').text.strip()movie_items.append({'title': title,'link': link,'rating': rating,'year': year})except (AttributeError, KeyError) as e:self.logger.warning(f"解析电影项时出错: {str(e)}")continueself.logger.info(f"成功解析 {len(movie_items)} 部电影")return movie_itemsexcept Exception as e:self.logger.error(f"解析页面时发生异常: {str(e)}")return []

3. 电影详情解析

def parse_movie_detail(self, html_content, base_info):if not html_content:return base_infotry:soup = BeautifulSoup(html_content, 'html.parser')director = soup.select_one('.director').text.strip() if soup.select_one('.director') else '未知'actors = [a.text.strip() for a in soup.select('.actors li')] if soup.select('.actors li') else []genre = [g.text.strip() for g in soup.select('.genre a')] if soup.select('.genre a') else []duration = soup.select_one('.duration').text.strip() if soup.select_one('.duration') else '未知'description = soup.select_one('.description').text.strip() if soup.select_one('.description') else ''movie_info = {**base_info,'director': director,'actors': actors,'genre': genre,'duration': duration,'description': description}return movie_infoexcept Exception as e:self.logger.error(f"解析详情页时发生异常: {str(e)}")return base_info

4. 爬虫主逻辑

def crawl(self, base_url, total_pages=1):self.logger.info(f"开始爬取电影信息,总页数: {total_pages}")for page in range(1, total_pages + 1):self.logger.info(f"正在爬取第 {page} 页...")# 获取电影列表页list_content = self.fetch_movie_list(base_url, page)# 解析电影列表movie_list = self.parse_movie_list(list_content)# 遍历电影列表,获取详情for movie in movie_list:# 构造完整详情页URLdetail_url = movie['link']if not detail_url.startswith('http'):detail_url = base_url + detail_url# 获取电影详情页detail_content = self.fetch_movie_detail(detail_url)# 解析电影详情full_movie_info = self.parse_movie_detail(detail_content, movie)# 添加到结果列表self.movies.append(full_movie_info)self.logger.info(f"成功获取电影: {full_movie_info['title']}")# 随机延时,避免过快请求time.sleep(random.uniform(1, 3))# 页面间延时time.sleep(random.uniform(2, 5))self.logger.info(f"爬取完成,共获取 {len(self.movies)} 部电影信息")

使用说明

  • 安装依赖

pip install requests beautifulsoup4 fake-useragent
  • 修改配置

    • 在代码中替换base_url为实际的电影网站 URL,并根据目标网站的 HTML 结构调整解析部分的 CSS 选择器。

  • 运行爬虫

python movie_crawler.py
  • 查看结果

    • 爬取的电影信息会保存到movies.json文件中。

注意事项

  • 法律合规

    • 此程序仅用于演示爬虫技术,请勿用于非法获取受版权保护的内容
    • 爬取网站前请查看其 robots.txt 文件和使用条款
    • 遵守相关国家和地区的法律法规
  • 反爬策略

    • 控制爬取速度,避免对目标网站造成压力
    • 添加合理的延时和请求头信息
    • 考虑使用代理 IP 池
  • 网站结构变化

    • 网站结构可能随时变化,需要相应调整解析代码
    • 建议添加适当的错误处理和重试机制
  • 数据使用限制

    • 爬取的数据仅供个人学习研究使用,不可用于商业用途
    • 尊重原网站的版权和数据使用政策
http://www.lryc.cn/news/2401132.html

相关文章:

  • MyBatis 的动态 SQL
  • Redis中的setIfAbsent方法和execute
  • 高考数学易错考点02 | 临阵磨枪
  • 国产高性能pSRAM选型指南:CSS6404LS-LI 64Mb QSPI伪静态存储器
  • Go 中 `json.NewEncoder/Decoder` 与 `json.Marshal/Unmarshal` 的区别与实践
  • UE5 2D角色PaperZD插件动画状态机学习笔记
  • Ubuntu 16.04 密码找回
  • 【论文阅读】DanceGRPO: Unleashing GRPO on Visual Generation
  • CentOS在vmware局域网内搭建DHCP服务器【踩坑记录】
  • AI炼丹日志-28 - Audiblez 将你的电子书epub转换为音频mp3 做有声书
  • 图像处理篇---face_recognition库实现人脸检测
  • 74. 搜索二维矩阵 (力扣)
  • 8088单板机C语言sprintf()格式化串口输出---Prj04
  • 板凳-------Mysql cookbook学习 (九)
  • 深入解析 Flask 命令行工具与 flask run命令的使用
  • 第6篇:中间件 SQL 重写与语义分析引擎实现原理
  • 基于SpringBoot的“嗨玩旅游”网站设计与实现(源码+定制+开发)嗨玩旅游平台开发:景点展示与个性化推荐系统(SpringBoot)
  • python版若依框架开发:python版若依部署
  • React进阶:状态管理选择题
  • h5的aliplayer-min.js 加密视频会走到debugger
  • 第5篇《中间件负载均衡与连接池管理机制设计》
  • DashBoard安装使用
  • 极客大挑战 2019 EasySQL 1(万能账号密码,SQL注入,HackBar)
  • C# CallerMemberName特性
  • 采用 Docker GPU 部署的 Ubuntu 或者 windows 桌面环境
  • 关于面试找工作的总结(四)
  • 分布式拜占庭容错算法——实现工作量证明(PoW)算法详解
  • 深度解析Mysql中MVCC的工作机制
  • MP4文件声音与视频分离
  • 接口自动化测试之pytest 运行方式及前置后置封装