爬虫阶段一实战练习题:爬取豆瓣电影 Top250 复盘

爬虫阶段一实战练习题:爬取豆瓣电影 Top250

  • [爬取豆瓣电影 Top250](#爬取豆瓣电影 Top250)

爬取豆瓣电影 Top250

练习一:爬取豆瓣电影 Top250

  • 目标https://movie.douban.com/top250
  • 数据字段:电影排名(1-250)、中文片名、导演、上映年份、评分、评价人数
  • 要求:分页爬取(共 10 页),保存为 CSV 文件。
  • 提示
    1. 第一页 URL:https://movie.douban.com/top250?start=0,第二页 start=25,以此类推。
    2. 需要设置 User-Agent 请求头,否则会返回 418。
    3. 使用 BeautifulSoup 解析,每个电影信息在一个 <li> 标签中,class="item"
    4. 电影排名在 <em> 标签中。
    5. 片名在 span 标签 class="title" 中(注意可能有英文名干扰,取第一个)。
    6. 导演等其他信息在 <p class=""> 中,需要正则或 split 处理。
    7. 评分在 span 标签 class="rating_num" 中。
    8. 评价人数在 <div class="star"> 内的最后一个 <span> 中,需提取数字。

抓取的电影数据示例:

html 复制代码
[<div class="item">
<div class="pic">
<em>1</em>
<a href="https://movie.douban.com/subject/1292052/">
<img alt="肖申克的救赎" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg" width="100"/>
</a>
</div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1292052/">
<span class="title">肖申克的救赎</span>
<span class="title"> / The Shawshank Redemption</span>
<span class="other"> / 月黑高飞(港)  /  刺激1995(台)</span>
</a>
<span class="playable">[可播放]</span>
</div>
<div class="bd">
<p>
                            导演: 弗兰克·德拉邦特 Frank Darabont   主演: 蒂姆·罗宾斯 Tim Robbins /...<br/>
                            1994 / 美国 / 犯罪 剧情
                        </p>
<div>
<span class="rating5-t"></span>
<span class="rating_num" property="v:average">9.7</span>
<span content="10.0" property="v:best"></span>
<span>3266928人评价</span>
</div>
<p class="quote">
<span>希望让人自由。</span>
</p>
</div>
</div>
</div>, <div class="item">
<div class="pic">
<em>2</em>
<a href="https://movie.douban.com/subject/1291546/">
<img alt="霸王别姬" src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2911205318.jpg" width="100"/>
</a>
</div>
<div class="info">
<div class="hd">
<a href="https://movie.douban.com/subject/1291546/">
<span class="title">霸王别姬</span>
<span class="other"> / 再见,我的妾  /  Farewell My Concubine</span>
</a>
<span class="playable">[可播放]</span>
</div>
<div class="bd">
<p>
                            导演: 陈凯歌 Kaige Chen   主演: 张国荣 Leslie Cheung / 张丰毅 Fengyi Zha...<br/>
                            1993 / 中国大陆 中国香港 / 剧情 爱情 同性
                        </p>
<div>
<span class="rating5-t"></span>
<span class="rating_num" property="v:average">9.6</span>
<span content="10.0" property="v:best"></span>
<span>2409980人评价</span>
</div>
<p class="quote">
<span>风华绝代。</span>
</p>
</div>
</div>
</div>,...]

调试后的爬虫代码

python 复制代码
import requests
from bs4 import BeautifulSoup
import re
import csv
import time

def fetch_page(start):
    url = f'https://movie.douban.com/top250?start={start}'
    headers = {'User-Agent': 'Mozilla/5.0'}
    #请求url
    resp = requests.get(url, headers=headers)
    #它的作用是把 HTML 字符串真正解析成 Python 对象。
    soup = BeautifulSoup(resp.text, 'lxml')
    movies = soup.select('.item')
    page_data = []
    for movie in movies:
        rank = movie.find('em').text
        title = movie.find('span', class_='title').text
        # 提取导演、年份等
        #strip()处理两端的字符
        infobd = movie.find('div', class_='bd')
        info = infobd.find('p').text.strip()
        #info2=   "导演: 文牧野 Muye Wen   主演: 徐峥 Zheng Xu / 王传君 Chuanjun Wang / 周...<br/>2018 / 中国大陆 / 剧情 喜剧"
        # 用正则或字符串分割提取导演和年份
        director_info = re.search(r'导演:(.*?)主演', info)
        if director_info:
            director = director_info.group(1).strip().replace('\xa0', '')
        year = re.search(r'\b(19|20)\d{2}\b', info).group()
        # 提取评分
        rating = movie.find('span', class_='rating_num').text

        # 提取评价人数
        people_span = movie.find ('span',string=re.compile(r'\d+人评价'))
        if people_span:
            people_text = people_span.get_text(strip=True)
            num = re.search(r'\d+', people_text).group()
        page_data.append([rank, title, director, year, rating, num])
    return page_data


all_data = [['排名', '片名', '导演', '年份', '评分', '评价人数']]
for i in range(0, 250, 25):
    all_data.extend(fetch_page(i))
    time.sleep(2)  # 礼貌延时

with open('douban_top250.csv', 'w', newline='', encoding='utf-8-sig') as f:
    writer = csv.writer(f)
    writer.writerows(all_data)

通过爬取豆瓣TOP250电影数据,你一定积累了不少宝贵的经验和技巧。下面从多个维度帮你梳理一下可能学到的内容,既是对知识的复盘,也能为后续项目提供参考。


一、HTML解析与数据提取

1. 识别页面结构

豆瓣TOP250每个电影条目都包裹在<div class="item">中,内部又分为pic(海报、排名)和info(详情)。学会用浏览器开发者工具(F12)快速定位元素,是爬虫的基本功。

2. 使用BeautifulSoup精准提取

  • 标题 :从<span class="title">获取中文名,注意可能有第二外语名(用<span class="title">的第二个或<span class="other">)。
  • 评分<span class="rating_num" property="v:average">直接取出数字。
  • 评价人数 :位于评分父节点内的最后一个<span>,文本如"3266928人评价"。通过.get_text()提取后用正则\d+抓取数字。
  • 引用语<p class="quote"><span>,若存在则直接取出。
  • 导演/主演/年份/地区/类型 :这些信息混在<p>标签的一段文本中,需要结合正则进一步提取。

3. 正则表达式的实战应用

  • 从混合文本中提取导演:r'导演:\s*(.*?)\s*主演',理解非贪婪匹配 .*?捕获组 (...),以及\s*匹配空白。
  • 提取年份:r'\b(19|20)\d{2}\b'或根据豆瓣格式r'(\d{4})\s*/\s*'
  • 注意特殊字符如不间断空格\xa0,通过.replace('\xa0', ' ')清洗。
  • match对象的方法.group(0)返回整个匹配,.group(1)返回第一个捕获组,.groups()返回所有捕获组元组。

二、分页处理与URL构造

1. 豆瓣分页规则

每页显示25条,通过start参数偏移:

  • 第1页:start=0
  • 第2页:start=25
  • ... 第10页:start=225

2. 循环构造URL

python 复制代码
base_url = "https://movie.douban.com/top250"
for start in range(0, 250, 25):
    url = f"{base_url}?start={start}&filter="
    # 请求并解析

这里range(0,250,25)生成10个页码,完美覆盖所有条目。


三、网络请求与反爬策略

1. 模拟浏览器请求

豆瓣对爬虫较敏感,必须添加请求头(尤其是User-Agent),否则可能返回403或重定向到登录页。

python 复制代码
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...'
}
requests.get(url, headers=headers)

2. 控制请求频率

在循环中适当time.sleep(1),避免请求过快导致IP被封。还可以使用requests.Session()保持连接,复用TCP。

3. 异常处理

网络波动、解析失败都可能发生,用try...except包裹关键代码,并打印错误信息,确保爬虫不会中途崩溃。


四、数据存储与清洗

1. 存储格式选择

  • CSV :标准表格格式,适合Excel打开,使用csv模块写入。
  • JSON:便于后续程序读取,结构清晰。
  • Excel :可用pandasopenpyxl直接生成。

2. 数据清洗

  • 去除字符串首尾空格:.strip()
  • 替换特殊空白:.replace('\xa0', ' ')
  • 数字类型转换:评价人数转为int,评分转为float,便于后续分析。

五、编码与文件处理

1. 避免中文乱码

  • 请求时,response.encoding可设为'utf-8'(豆瓣返回的编码通常是utf-8)。
  • 写入CSV时,指定encoding='utf-8-sig',防止Excel打开乱码。

2. 文件操作

使用with open(...) as f确保文件正确关闭,是良好的编程习惯。


六、调试与模块化

1. 分步调试

每解析一个字段,就print一下结果,确保提取正确后再继续。可以用Jupyter Notebook交互式调试。

2. 函数封装

将获取页面、解析单页、保存数据等功能拆分为独立函数,提高代码可读性和复用性。例如:

python 复制代码
def get_page(url):
    # 请求并返回soup

def parse_item(item):
    # 从单个item提取数据,返回字典

def save_to_csv(data_list):
    # 写入文件

3. 使用if __name__ == '__main__':

防止模块被导入时执行爬虫代码。


七、法律与道德

  • 遵守robots.txt :豆瓣的robots.txt禁止了某些路径,但TOP250通常是允许的。
  • 适度爬取:不要对服务器造成压力,添加延时。
  • 数据仅用于学习:避免商用或大量分发,尊重版权。

八、数据分析的延伸思考

爬下来的数据还可以进一步探索:

  • 评分分布:哪些分数段电影最多?
  • 年份趋势:哪个年代出产的高分电影最多?
  • 导演/演员频次:谁的作品上榜最多?
  • 类型分析:剧情、犯罪、爱情等类型的占比。

可以结合pandasmatplotlib做可视化,让爬虫成果更有趣。


通过这次实战,你不仅掌握了爬虫的基本流程(请求→解析→存储),还深入了解了HTML结构、正则表达式、反爬策略等实用技能。这些知识完全可以迁移到其他网站的爬取中,是成为数据工程师/分析师的重要一步。如果在总结中还有不清楚的地方,或者想深入探讨某个细节,随时欢迎继续交流!

相关推荐
郭龙_Jack2 小时前
TensorFlow GPU 优化配置手册
人工智能·python·tensorflow
HAPPY酷2 小时前
C++ 多文件编程:声明、定义与全局变量的“黄金法则”
c++·python·技术美术
Java咩2 小时前
LangChain 之 LCEL表达式语法
python·langchain·lcel
LaughingZhu2 小时前
Product Hunt 每日热榜 | 2026-03-11
大数据·数据库·人工智能·经验分享·搜索引擎
ADHD多动联盟2 小时前
ADHD注意力缺陷是什么?主要有儿童ADHD和多动症运动干预吗?
学习·学习方法·玩游戏
white-persist2 小时前
【红队渗透】Cobalt Strike(CS)红队详细用法实战手册
java·网络·数据结构·python·算法·安全·web安全
geovindu3 小时前
python: Adapter Pattern
java·python·设计模式·适配器模式
weixin_443478513 小时前
flutter组件学习之Stack 组件详解
学习·flutter
Beginner x_u3 小时前
Vue scoped 样式不生效的一个坑:CSS 选择器与 class 合并机制
前端·css·vue.js