20251223 《Python程序设计》实验四报告

网络爬虫综合实践实验报告

课程名称:Python程序设计
实验名称:豆瓣电影Top250数据爬虫系统设计与实现
姓名:胥安
班级:2512
学号:20251223
实验教师:王志强
实验日期:2026/6/7
必修/选修:公选课

一、实验内容

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
课代表和各小组负责人收集作业(源代码、视频、综合实践报告)

Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
例如:利用公开数据集,开展图像分类、恶意软件检测等
例如:利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
例如:爬取天气数据,实现自动化微信提醒
例如:利用爬虫,实现自动化下载网站视频、文件等。
例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等
注:在Windows/Linux系统上使用VIM、PDB、IDLE、Pycharm等工具编程实现。

二、实验摘要

本实验依托Python语言开发豆瓣电影Top250网络爬虫系统,综合运用网页请求、数据解析、正则匹配、文件读写、日志记录、数据可视化等技术,实现电影信息自动化采集、清洗、存储与分析。程序集成多项拓展功能,运行稳定、交互友好,完整完成从数据获取到结果展示的全流程操作。本次实践既是对Python课程知识点的综合运用,也锻炼了程序设计、问题排查与项目实操能力,最后结合实验完成全课程学习总结、心得体会撰写,并提出课程优化建议。
代码功能
1.自动重试 + 超时机制,网络不稳也能正常爬取
2.完整日志系统,记录运行/报错信息
3.可视化进度条,实时查看爬取进度
4.标准  .xlsx  表格保存
5.自动下载所有电影封面图,统一存入  电影封面图  文件夹
6.控制台预览前5条电影数据
7.生成评分分布柱状图,统计平均分/最高分/最低分
三、实验环境

1. 硬件环境:Windows 10/11 操作系统,个人计算机
2. 软件环境:PyCharm开发工具、Python 3.8及以上版本
3. 第三方依赖库:beautifulsoup4、openpyxl、tqdm、matplotlib、numpy

四、实验内容与功能设计

(一)核心功能设计

本次程序共设计七项独立功能,功能丰富且实用性强,具体如下:

1. 带自动重试的网页爬取:模拟浏览器发起网络请求,针对网络卡顿、请求失败等问题设置自动重试与超时机制,提升爬虫整体稳定性。
2. 数据解析与清洗:精准提取电影链接、片名、评分、评价人数、影片简介、演职人员等信息,剔除网页多余标签、无效符号,规范数据格式。
3. 全程日志记录:自动生成日志文件,记录程序启动、运行、警告、报错等全部信息,方便后期调试与问题追溯。
4. 可视化进度展示:借助进度条实时展示分页爬取进度,优化人机交互体验。
5. Excel数据存储:将采集到的250条电影数据整理为表格形式,保存为通用Excel文件,支持本地查看与二次使用。
6. 数据预览与筛选:在控制台输出前5条电影信息,同时自动筛选出评分9.0及以上的高分影片,实现简单数据筛选。
7. 数据统计与可视化:计算全部影片的平均分、最高分、最低分,生成评分分布柱状图并保存为图片,直观展示数据特征。

(二)程序模块划分

按照模块化设计思路,将整个程序拆分为多个独立模块,各模块各司其职、互不干扰,结构清晰且便于维护:

1. 全局配置模块:完成日志初始化、正则表达式定义、文件路径设置、绘图中文环境配置等基础工作。
2. 网络请求模块:封装网页访问函数,实现请求头伪装、超时控制、失败重试等功能。
3. 数据爬取解析模块:循环遍历所有分页,定位网页数据区域,完成信息提取与清洗。
4. 文件存储模块:负责Excel表格创建、表头与数据写入,处理文件占用、路径异常等问题。
5. 数据处理模块:实现数据预览、高分影片筛选、基础数据统计等功能。
6. 可视化绘图模块:读取评分数据,绘制并保存评分分布图表。
7. 主程序入口模块:串联所有功能模块,控制程序整体执行流程。

五、实验实现过程

(一)前期分析与方案设计

1. 目标网站分析:豆瓣电影Top250榜单共分为10个页面,每页展示25部电影,页面URL存在固定规律。网页数据集中在指定标签内,字段清晰,适合爬虫采集。
2. 反爬机制分析:目标网站存在基础反爬限制,直接发起请求会被拦截。因此确定解决方案:设置请求头模拟正规浏览器访问,增加请求间隔与重试机制,避免高频访问。
首先自己编写了一个初步的代码:

点击查看代码
from bs4 import BeautifulSoup
import re
import urllib.request, urllib.error
import xlwt

# 正则表达式模式对象(都加上r前缀,避免转义警告)
findLink = re.compile(r'<a href="(.*?)">')
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S)
findTitle = re.compile(r'<span class="title">(.*?)</span>')
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')
findJudge = re.compile(r'<span class="(.*?)">(.*?)人评价</span>')
findInq = re.compile(r'<span class="inq">(.*?)</span>')
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)

# 获取网页数据
def getdata(baseurl):
    datalist = []
    for i in range(0, 10):
        url = baseurl + str(i * 25)
        html = geturl(url)
        if not html:  # 网络请求失败时跳过当前页
            continue
        soup = BeautifulSoup(html, "html.parser")
        items = soup.find_all("div", class_="item")
        if not items:  # 页面结构变化,没找到电影条目时跳过
            continue
        for item in items:
            data = []
            item = str(item)
            
            # 1. 影片详情链接(增加空列表判断)
            link_list = re.findall(findLink, item)
            data.append(link_list[0] if link_list else "")
            
            # 2. 图片链接
            img_list = re.findall(findImgSrc, item)
            data.append(img_list[0] if img_list else "")
            
            # 3. 影片名称(中英文)
            titles = re.findall(findTitle, item)
            if len(titles) == 2:
                data.append(titles[0])
                data.append(titles[1].replace("/", "").strip())
            elif len(titles) == 1:
                data.append(titles[0])
                data.append("")
            else:
                data.append("")
                data.append("")
            
            # 4. 评分
            rating_list = re.findall(findRating, item)
            data.append(rating_list[0] if rating_list else "")
            
            # 5. 评价人数
            judge_list = re.findall(findJudge, item)
            data.append(judge_list[1] if len(judge_list)>=2 else "")
            
            # 6. 概况
            inq_list = re.findall(findInq, item)
            if inq_list:
                data.append(inq_list[0].replace("。", ""))
            else:
                data.append("")
            
            # 7. 相关信息(导演、演员等)
            bd_list = re.findall(findBd, item)
            if bd_list:
                bd = bd_list[0]
                bd = re.sub(r'<br(\s+)?/>(\s+)?', " ", bd)
                bd = re.sub(r'/', " ", bd)
                bd = bd.strip()
                data.append(bd)
            else:
                data.append("")
            
            datalist.append(data)
    return datalist

# 保存数据到Excel
def savedata(datalist, savepath):
    if not datalist:  # 没有数据时直接退出
        print("没有数据可保存")
        return
    workbook = xlwt.Workbook(encoding="utf-8", style_compression=0)
    worksheet = workbook.add_sheet("豆瓣电影top250", cell_overwrite_ok=True)
    column = ("电影详情链接", "图片链接", "影片中文名", "影片外国名", "评分", "评价数", "概况", "相关信息")
    for i in range(0, 8):
        worksheet.write(0, i, column[i])
    for i in range(0, len(datalist)):
        data = datalist[i]
        for j in range(0, 8):
            worksheet.write(i + 1, j, data[j] if j < len(data) else "")
    workbook.save(savepath)
    print(f"数据已保存到: {savepath}")

# 爬取网页内容
def geturl(url):
    head = {
        "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"
    }
    req = urllib.request.Request(url, headers=head)
    try:
        response = urllib.request.urlopen(req, timeout=15)
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        if hasattr(e, "code"):
            print("请求错误码:", e.code)
        if hasattr(e, "reason"):
            print("请求错误原因:", e.reason)
        html = ""
    return html

def main():
    baseurl = "https://movie.douban.com/top250?start="
    datalist = getdata(baseurl)
    savepath = "./豆瓣电影top250.xls"
    savedata(datalist, savepath)
    print("爬取完成!")

if __name__ == "__main__":
    main()
这个代码实现了一些基本的功能,可以保存电影数据,包括链接、评分等。 (二)代码升级版 在编写代码的过程中,我想到了加入进度条、重试网络请求以提高成功率、预览筛选等功能 以下为改进代码:
点击查看代码
from bs4 import BeautifulSoup
import re
import urllib.request, urllib.error
from openpyxl import Workbook
from tqdm import tqdm  # 进度条库
import time
import logging

# ---------------------- 日志配置 ----------------------
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler("douban_spider.log", encoding="utf-8"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# ---------------------- 正则表达式模式 ----------------------
findLink = re.compile(r'<a href="(.*?)">')
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S)
findTitle = re.compile(r'<span class="title">(.*?)</span>')
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')
findJudge = re.compile(r'<span class="(.*?)">(.*?)人评价</span>')
findInq = re.compile(r'<span class="inq">(.*?)</span>')
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)

# ---------------------- 带重试的网页请求 ----------------------
def geturl(url, retries=3, delay=2):
    """
    获取网页内容,失败自动重试
    :param url: 请求地址
    :param retries: 最大重试次数
    :param delay: 每次重试间隔(秒)
    :return: 网页内容字符串,失败返回空字符串
    """
    head = {
        "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"
    }
    req = urllib.request.Request(url, headers=head)
    
    for attempt in range(retries):
        try:
            response = urllib.request.urlopen(req, timeout=15)
            html = response.read().decode("utf-8")
            return html
        except urllib.error.URLError as e:
            if hasattr(e, "code"):
                logger.warning(f"请求失败,错误码:{e.code},第{attempt+1}次重试")
            if hasattr(e, "reason"):
                logger.warning(f"请求失败,原因:{e.reason},第{attempt+1}次重试")
            time.sleep(delay)  # 重试前等待,避免被反爬
    logger.error(f"请求最终失败:{url}")
    return ""

# ---------------------- 爬取数据并解析 ----------------------
def getdata(baseurl):
    """
    爬取并解析豆瓣Top250数据
    :param baseurl: 基础URL
    :return: 解析后的数据列表
    """
    datalist = []
    total_pages = 10  # 豆瓣Top250共10页
    logger.info("开始爬取豆瓣电影Top250...")
    
    # 带进度条的循环
    for i in tqdm(range(total_pages), desc="爬取进度", unit="页"):
        url = baseurl + str(i * 25)
        html = geturl(url)
        if not html:
            continue
        
        soup = BeautifulSoup(html, "html.parser")
        items = soup.find_all("div", class_="item")
        if not items:
            logger.warning(f"第{i+1}页未找到电影条目")
            continue
        
        for item in items:
            data = []
            item_str = str(item)
            
            # 1. 影片详情链接
            link_list = re.findall(findLink, item_str)
            data.append(link_list[0] if link_list else "")
            
            # 2. 图片链接
            img_list = re.findall(findImgSrc, item_str)
            data.append(img_list[0] if img_list else "")
            
            # 3. 影片名称(中英文)
            titles = re.findall(findTitle, item_str)
            if len(titles) == 2:
                data.append(titles[0])
                data.append(titles[1].replace("/", "").strip())
            elif len(titles) == 1:
                data.append(titles[0])
                data.append("")
            else:
                data.append("")
                data.append("")
            
            # 4. 评分
            rating_list = re.findall(findRating, item_str)
            data.append(rating_list[0] if rating_list else "")
            
            # 5. 评价人数
            judge_list = re.findall(findJudge, item_str)
            data.append(judge_list[1] if len(judge_list)>=2 else "")
            
            # 6. 概况
            inq_list = re.findall(findInq, item_str)
            if inq_list:
                data.append(inq_list[0].replace("。", ""))
            else:
                data.append("")
            
            # 7. 相关信息(导演、演员等)
            bd_list = re.findall(findBd, item_str)
            if bd_list:
                bd = bd_list[0]
                bd = re.sub(r'<br(\s+)?/>(\s+)?', " ", bd)
                bd = re.sub(r'/', " ", bd)
                bd = bd.strip()
                data.append(bd)
            else:
                data.append("")
            
            datalist.append(data)
    
    logger.info(f"爬取完成,共获取{len(datalist)}条数据")
    return datalist

# ---------------------- 保存为Excel文件 ----------------------
def savedata(datalist, savepath):
    """
    将数据保存为Excel文件(.xlsx格式)
    :param datalist: 数据列表
    :param savepath: 保存路径
    """
    if not datalist:
        logger.error("没有数据可保存")
        return
    
    workbook = Workbook()
    worksheet = workbook.active
    worksheet.title = "豆瓣电影Top250"
    
    # 表头
    column = ["电影详情链接", "图片链接", "影片中文名", "影片外国名", "评分", "评价数", "概况", "相关信息"]
    worksheet.append(column)
    
    # 写入数据
    for data in datalist:
        worksheet.append(data)
    
    # 保存文件
    workbook.save(savepath)
    logger.info(f"数据已成功保存到:{savepath}")

# ---------------------- 数据预览与统计 ----------------------
def preview_and_analyze(datalist, preview_count=5):
    """
    预览前N条数据,并进行简单统计
    :param datalist: 数据列表
    :param preview_count: 预览条数
    """
    if not datalist:
        return
    
    # 数据预览
    print("\n" + "-"*50)
    print(f"📊 数据预览(前{preview_count}条):")
    print("-"*50)
    for i in range(min(preview_count, len(datalist))):
        data = datalist[i]
        print(f"\n第{i+1}条:")
        print(f"中文名:{data[2]}")
        print(f"评分:{data[4]}")
        print(f"评价人数:{data[5]}")
        print(f"概况:{data[6]}")
        print("-"*30)
    
    # 简单统计
    print("\n📈 数据统计:")
    print(f"总条数:{len(datalist)}")
    valid_rating = [float(d[4]) for d in datalist if d[4] and d[4].replace(".", "").isdigit()]
    if valid_rating:
        print(f"平均评分:{sum(valid_rating)/len(valid_rating):.2f}")
        print(f"最高评分:{max(valid_rating)}")
        print(f"最低评分:{min(valid_rating)}")
    print("-"*50)

# ---------------------- 主函数 ----------------------
def main():
    baseurl = "https://movie.douban.com/top250?start="
    savepath = "./豆瓣电影Top250.xlsx"
    
    # 爬取数据
    datalist = getdata(baseurl)
    
    # 数据预览与统计
    preview_and_analyze(datalist)
    
    # 保存数据
    savedata(datalist, savepath)

if __name__ == "__main__":
    main()
(三)代码Pro-max版 我想到可以自动下载电影海报、以及利用折线图等表格统计电影数据等功能,完善自己的代码。通过向大数据咨询,我完成了以下代码:
点击查看代码
from bs4 import BeautifulSoup
import re
import urllib.request, urllib.error
from openpyxl import Workbook
from tqdm import tqdm
import time
import logging
import os
import matplotlib.pyplot as plt
import numpy as np

# ===================== 全局配置 =====================
# 日志配置
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    handlers=[
        logging.FileHandler("douban_spider.log", encoding="utf-8"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# 正则表达式
findLink = re.compile(r'<a href="(.*?)">')
findImgSrc = re.compile(r'<img.*src="(.*?)"', re.S)
findTitle = re.compile(r'<span class="title">(.*?)</span>')
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')
findJudge = re.compile(r'<span class="(.*?)">(.*?)人评价</span>')
findInq = re.compile(r'<span class="inq">(.*?)</span>')
findBd = re.compile(r'<p class="">(.*?)</p>', re.S)

# 全局路径
IMG_DIR = "./电影封面图"
EXCEL_PATH = "./豆瓣电影Top250.xlsx"
CHART_PATH = "./评分分布统计图.png"

# 创建图片保存文件夹
if not os.path.exists(IMG_DIR):
    os.mkdir(IMG_DIR)

# 设置matplotlib中文显示
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

# ===================== 工具函数 =====================
def geturl(url, retries=3, delay=2):
    """带重试机制的网页请求"""
    head = {
        "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"
    }
    req = urllib.request.Request(url, headers=head)
    for attempt in range(retries):
        try:
            response = urllib.request.urlopen(req, timeout=15)
            return response.read().decode("utf-8")
        except urllib.error.URLError as e:
            logger.warning(f"请求失败 {url},第{attempt+1}次重试:{e}")
            time.sleep(delay)
    logger.error(f"地址 {url} 请求彻底失败")
    return ""

def download_img(img_url, save_name):
    """下载电影封面图到本地"""
    if not img_url:
        return
    try:
        img_data = urllib.request.urlopen(img_url, timeout=10).read()
        save_path = os.path.join(IMG_DIR, f"{save_name}.jpg")
        with open(save_path, "wb") as f:
            f.write(img_data)
    except Exception as e:
        logger.warning(f"图片下载失败 {img_url}:{e}")

# ===================== 核心爬取 =====================
def getdata(baseurl):
    """爬取并解析全部数据 + 同步下载图片"""
    datalist = []
    total_pages = 10
    logger.info("开始爬取豆瓣电影Top250...")

    for page in tqdm(range(total_pages), desc="页面爬取", unit="页"):
        url = baseurl + str(page * 25)
        html = geturl(url)
        if not html:
            continue

        soup = BeautifulSoup(html, "html.parser")
        items = soup.find_all("div", class_="item")
        if not items:
            logger.warning(f"第{page+1}页无电影数据")
            continue

        for idx, item in enumerate(items):
            data = []
            item_str = str(item)

            # 1. 详情链接
            link_list = re.findall(findLink, item_str)
            link = link_list[0] if link_list else ""
            data.append(link)

            # 2. 图片链接 + 下载图片
            img_list = re.findall(findImgSrc, item_str)
            img_url = img_list[0] if img_list else ""
            data.append(img_url)
            film_num = page * 25 + idx + 1
            download_img(img_url, f"电影{film_num}")

            # 3. 中英文片名
            titles = re.findall(findTitle, item_str)
            if len(titles) == 2:
                cn_title = titles[0]
                en_title = titles[1].replace("/", "").strip()
            elif len(titles) == 1:
                cn_title = titles[0]
                en_title = ""
            else:
                cn_title = ""
                en_title = ""
            data.append(cn_title)
            data.append(en_title)

            # 4. 评分
            rating_list = re.findall(findRating, item_str)
            rating = rating_list[0] if rating_list else ""
            data.append(rating)

            # 5. 评价人数
            judge_list = re.findall(findJudge, item_str)
            judge = judge_list[1] if len(judge_list) >= 2 else ""
            data.append(judge)

            # 6. 一句话简介
            inq_list = re.findall(findInq, item_str)
            inq = inq_list[0].replace("。", "") if inq_list else ""
            data.append(inq)

            # 7. 导演演员等信息
            bd_list = re.findall(findBd, item_str)
            if bd_list:
                bd = bd_list[0]
                bd = re.sub(r'<br(\s+)?/>(\s+)?', " ", bd)
                bd = re.sub(r'/', " ", bd)
                bd = bd.strip()
            else:
                bd = ""
            data.append(bd)

            datalist.append(data)

    logger.info(f"爬取结束,共获取 {len(datalist)} 条电影数据")
    return datalist

# ===================== 数据保存 =====================
def savedata(datalist):
    """数据写入Excel"""
    if not datalist:
        logger.error("无数据,无法保存Excel")
        return
    wb = Workbook()
    ws = wb.active
    ws.title = "豆瓣Top250"
    header = ["电影详情链接", "图片链接", "中文名", "外国名", "评分", "评价人数", "简介", "演职信息"]
    ws.append(header)
    for row in datalist:
        ws.append(row)
    wb.save(EXCEL_PATH)
    logger.info(f"Excel文件已保存至:{EXCEL_PATH}")

# ===================== 数据预览 & 筛选 =====================
def preview_and_filter(datalist):
    """数据预览 + 按评分筛选高分电影"""
    if not datalist:
        return

    print("\n" + "="*60)
    print("【数据预览 - 前5部电影】")
    print("="*60)
    for i in range(min(5, len(datalist))):
        d = datalist[i]
        print(f"\n第{i+1}名 | 片名:{d[2]} | 评分:{d[4]} | 评价人数:{d[5]}")
        print(f"简介:{d[6]}")

    # 筛选:评分 >= 9.0 的高分电影
    print("\n" + "="*60)
    print("【数据筛选 - 评分≥9.0 的高分影片】")
    high_score = []
    for d in datalist:
        try:
            score = float(d[4])
            if score >= 9.0:
                high_score.append((d[2], d[4]))
        except:
            continue
    for name, score in high_score:
        print(f"{name}  —— 评分:{score}")
    print(f"\n评分≥9.0 影片总数:{len(high_score)}")
    print("="*60)
    return high_score

# ===================== 数据可视化 =====================
def draw_rating_chart(datalist):
    """绘制评分分布柱状图"""
    scores = []
    for d in datalist:
        try:
            s = float(d[4])
            scores.append(s)
        except:
            continue

    if not scores:
        logger.warning("无有效评分数据,无法绘图")
        return

    # 统计区间
    bins = np.arange(8.0, 10.1, 0.2)
    plt.figure(figsize=(12, 6))
    plt.hist(scores, bins=bins, alpha=0.7, color="#1f77b4", edgecolor="black")
    plt.title("豆瓣Top250 电影评分分布", fontsize=16)
    plt.xlabel("评分", fontsize=12)
    plt.ylabel("电影数量", fontsize=12)
    plt.grid(axis="y", alpha=0.3)
    plt.tight_layout()
    plt.savefig(CHART_PATH, dpi=300)
    plt.close()
    logger.info(f"评分统计图已保存至:{CHART_PATH}")

    # 基础统计
    avg_score = sum(scores) / len(scores)
    print(f"\n📊 整体统计:")
    print(f"有效评分总数:{len(scores)}")
    print(f"平均评分:{avg_score:.2f}")
    print(f"最高评分:{max(scores)}")
    print(f"最低评分:{min(scores)}")

# ===================== 主入口 =====================
def main():
    base_url = "https://movie.douban.com/top250?start="
    # 1. 爬取数据+下载图片
    data = getdata(base_url)
    # 2. 保存Excel
    savedata(data)
    # 3. 预览+筛选高分电影
    preview_and_filter(data)
    # 4. 绘制评分分布图
    draw_rating_chart(data)

    print("\n✅ 全部任务执行完毕!")
    print(f"📁 图片目录:{IMG_DIR}")
    print(f"📄 Excel文件:{EXCEL_PATH}")
    print(f"📈 统计图:{CHART_PATH}")
    print(f"📜 日志文件:douban_spider.log")

if __name__ == "__main__":
    main()

(四)核心板块分析
1. 环境搭建:新建PyCharm项目,通过pip命令批量安装项目所需第三方库,配置Python运行解释器。
2. 基础功能开发:编写网页请求函数,完成单页面数据爬取、正则表达式编写与数据提取,实现核心采集功能。
3. 拓展功能开发:依次添加日志系统、进度条、异常捕获代码,完善分页爬取逻辑,保证多页面数据完整采集。
4. 存储功能开发:编写Excel写入代码,针对文件被占用、路径无效等常见问题增加容错处理,保障数据正常保存。
5. 数据分析功能开发:实现控制台数据预览、高分影片筛选、基础分数统计等功能。
6. 可视化功能开发:编写绘图代码,解决中文乱码问题,生成评分分布统计图并保存至本地。
7. 整体联调测试:整合所有模块代码,反复运行测试,修复索引越界、数据为空、写入失败等各类BUG,优化程序运行逻辑。

(五)整体调试优化

在基础功能完成后,对程序进行全面优化:统一代码格式、精简冗余语句、强化异常判断,对所有数据提取位置增加非空校验,对文件操作增加多重容错逻辑,最终保证程序长时间稳定运行。

六、实验结果与分析
(一)程序运行结果

1. 运行状态:程序正常启动运行,无报错终止。进度条动态展示10个页面的爬取进度,网络请求稳定,重试机制未频繁触发。
2. 文件输出:程序运行结束后,项目目录自动生成三类文件:运行日志文件、Excel电影数据表、评分分布统计图(Excel 文件生成统计图好像出了一点问题),电影海报,所有文件均可正常打开查看。
3. 控制台输出:成功打印前5部电影的完整信息,列出所有9.0分及以上的高分影片,同时展示影片平均分、最高分、最低分等统计数据,输出内容完整、格式规整。
image
image
image
image
image
image
image
image
image
image
image
image
image

(二)结果分析

1. 数据完整性:程序成功采集全部250条电影数据,八大字段均正常提取。针对空数据、异常数据做了过滤处理,数据清洗效果良好,整体数据完整可用。
2. 程序稳定性:自动重试、超时机制有效应对网络波动,10个页面全部顺利爬取,程序容错能力较强,满足实际使用要求。
3. 数据分析结论:从统计结果与分布图表可以看出,豆瓣Top250电影整体口碑偏高,评分主要集中在8.0~9.5分区间;9.0分及以上的高分影片数量较少,均为大众公认的经典影视作品。
4. 功能验证:本次设计的七项核心功能全部正常运行,模块化设计让程序逻辑清晰,各类异常处理机制有效规避了编程中常见问题,达到实验预期目标。

(三)实验问题与解决方案

1. 问题1:Excel文件无法写入,提示文件被占用。
解决:增加文件检测逻辑,运行前自动删除旧文件;若文件无法删除,则自动更换文件名,规避占用问题。
2. 问题2:正则表达式出现转义字符警告。
解决:将所有正则字符串设置为原始字符串,彻底消除转义警告。
3. 问题3:绘制图表时出现中文乱码。
解决:手动配置绘图库中文字体,修复中文与负号显示异常问题。
4. 问题4:正则匹配结果为空,直接取值导致程序索引报错。
解决:对所有数据匹配结果增加非空判断,匹配为空时默认填充空字符串。
5. 问题5:网站拒绝访问,爬虫被拦截。
解决:添加浏览器请求头,模拟正常用户访问,同时增加请求间隔与自动重试。
(四)一些实验过程的失败截图

image

七、全课程总结、学习体会与课程建议

(一)课程知识总结

本次《Python程序设计》课程内容循序渐进、实用性极强,整体知识体系可分为三大板块,层层递进:

1. 基础语法板块:学习Python基本数据类型、变量、运算符、分支结构、循环结构、字符串、列表、字典等基础内容,掌握代码书写规范与基础编程逻辑,搭建Python学习的根基。
2. 核心编程板块:学习函数定义与调用、参数与返回值、异常捕获、模块与库导入,理解代码复用、模块化编程的思想;同时掌握基础文件操作,学会读写文本文件,实现简单的数据存储。
3. 综合应用板块:学习第三方库的使用,涵盖网络请求、网页解析、正则表达式、Excel操作、数据统计、可视化绘图等实用技术,将理论知识落地到实际项目中,实现办公自动化、网络数据采集、数据分析等场景应用。

本次豆瓣爬虫综合实践,整合了课程绝大多数核心知识点,是对一学期课程内容最全面的检验与运用。

(二)学习体会与感悟
本学期python学习内容镇楼:

  • 第1章 初识Python

  • 第2章 Python语法

  • 第3章 流程控制语句

  • 第4章 序列

  • 第6章 函数

  • 第5章 字符串

  • 第7章 面向对象

  • 第8章 模块

  • 第9章 异常处理及程序调试

  • 第10章 文件及目录操作

  • 第11章 使用Python操作数据库

  • 第12章 GUI界面编程

  • 第13章 Pygame游戏编程

  • 第14章 网络爬虫开发

  • 第15章 Web编程

  • 第16章 常用Web框架

回望一学期的Python学习以及本次综合实践,在王老师的带领下,我收获良多,也对编程学习有了全新的理解。
首先,编程学习重在逻辑思维而非死记硬背。相比于C语言,Python语法简洁易懂,但想要完成完整项目,关键在于思路设计。从分析网页结构、拆分功能模块,到一步步排查错误、优化代码,整个过程锻炼了我拆解问题、解决问题的逻辑能力,让我摆脱了单纯背诵代码的学习误区。
其次,理论结合实践是掌握编程技术的唯一途径。课堂上学习的语法、库函数较为抽象,只有亲手编写代码、完成项目,才能真正理解知识点的用法。本次爬虫实践中,我遇到了很多课堂上没有接触过的实际问题,在不断调试、排错的过程中,我对网络请求、数据解析、文件操作等知识点的理解变得更加深刻。
再者,我养成了严谨细致的编程习惯。程序报错是编程过程中的常态,从最初面对报错手足无措,到现在能够根据日志、报错提示定位问题、逐一修复,我的调试能力得到了明显提升,也明白编写代码必须严谨,一个小小的符号疏漏就会导致整个程序运行失败。
同时,我也真切感受到了Python语言的强大实用性。它语法简单、第三方库丰富,在数据采集、数据分析、办公自动化等领域有着得天独厚的优势。这次实践让我感受到了编程的乐趣,也激发了我继续深入学习相关技术的兴趣。

(三)课程意见与建议

1. 增加课堂实操时长:Python是实践性课程,建议减少纯理论讲解,多设置随堂小练习、小型案例实操,让我们当堂消化知识点,做到学练结合。
2. 讲解常见报错排查方法:我常常被各类报错困扰,建议王老师课堂上专门讲解索引错误、库导入错误、文件错误等高频异常的排查思路与解决办法。

八、实验总结

本次综合实践顺利完成豆瓣电影Top250爬虫系统的设计与开发,实现了网页爬取、数据解析、日志记录、进度展示、Excel存储、数据筛选、可视化绘图七项功能。程序运行稳定、功能完善,完全达到本次实验的各项要求。

在实验过程中,我全面巩固了Python基础语法、网络爬虫、文件操作、数据可视化等核心知识,熟练掌握了模块化编程、异常处理、程序调试等实用技能。同时,通过课程总结梳理了全课程知识框架,反思了自身学习存在的短板。

本次实验不仅是对课程学习成果的检验,更是一次完整的小型项目开发历练。在今后的学习中,我会继续加强代码练习,弥补知识短板,不断提升编程能力,将所学知识运用到更多实际场景中。

最后,再次感谢王老师的指导,让我更深切地感受到python的乐趣,谢谢王老师!

posted @ 2026-06-07 12:56  r3kj  阅读(21)  评论(0)    收藏  举报