【Python】– 使用BeautifulSoup爬取豆瓣电影Top250榜单

        豆瓣是中国的一个社区网站,创立于2005年3月6日,以书影音起家,提供关于书籍、电影、音乐等作品的信息。其中,豆瓣电影Top250榜单是其“明星产品”,被网友誉为“人生必看电影清单”。本文将从BeautifulSoup简介,具体代码步骤和对应逻辑,以及完整的代码实现三部分向您详细介绍如何使用 Python 中的 BeautifulSoup 爬取豆瓣电影Top250榜单

        本文中的代码操作将基于 Python 实现并建议您使用 Anaconda Jupyter Notebook 作为代码的编辑器。实现爬虫的完整代码已经放置在文章结尾。

0. BeautifulSoup简介

        BeautifulSoup 是一个 Python 包,功能包括解析 HTML 和 XML 文档、修复含有未闭合标签等错误的文档。这个扩展包为待解析的页面建立一棵树,以便提取其中的数据。BeautifulSoup 本身并不提供网络连接功能,它通常与像 requests 这样的HTTP库一起使用,以便从网络上获取 HTML 或 XML 内容,并随后使用 BeautifulSoup 来解析这些数据。

      目前,BeautifulSoup常被用于网页爬虫、数据抓取、自动化测试等场景中。这是BeautifulSoup的官方参考文档:Beautiful Soup Documentation — Beautiful Soup 4.12.0 documentation

1. 明确爬取目标及信息结构

        在使用Python对豆瓣电影Top250榜单之前,我们需要明确爬取的目标网站需要的信息

  • 目标网站:豆瓣电影Top250榜单  豆瓣电影 Top 250
  • 需要的信息:电影标题、评分、评价人数、电影简介、电影链接
  • 2. 环境配置并导入必要的库

            首先,可以使用如下命令在您的电脑中安装如下的Python包:BeautifulSoup(用于解析 HTML 数据)、requests(用于发送 HTTP 请求)、pandas(用于存储和组织爬取的数据)。

    pip install requests beautifulsoup4 pandas

            下载完成后,您需要导入这些库。

    import requests
    from bs4 import BeautifulSoup
    import pandas as pd
    import time

    3. 获取HTML内容

            在导入BeautifulSoup、requests、pandas后,我们需要获取 HTML 内容。本部分的代码将使用 requests 来实现 HTTP 请求。requests 是 Python 中一个功能强大且简单易用的 HTTP 库,常用于发送 HTTP 请求以获取网页内容、调用API或提交数据。我们将主要使用 requests.get 功能。关于 requests 的详细信息,可参考相关技术文档:GitHub – psf/requests: A simple, yet elegant, HTTP library.

            在这部分,我们首先将使用 requests.get (url, headers=headers, timeout=10) 发送一个GET请求到指定的URL。其中,url 表示目标网页的网址;headers 用于模拟浏览器;timeout 表示的是超过时间,确保程序不会因为网络延迟无限等待。之后,我们将等待服务器返回响应,实现代码包括 response.text(获取网页的HTML内容)和 response.status_code(HTTP 状态码,用于判断请求是否成功)。

            我们在这部分代码中设计了一个错误处理,即 except requests.RequestException as e,用于捕捉网络异常(如连接超时、域名解析失败等)。

    def get_html(url):
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
        }
        try:
            response = requests.get(url, headers=headers, timeout=10)
            if response.status_code == 200:
                return response.text
            else:
                print(f"请求失败,状态码:{response.status_code}")
                return None
        except requests.RequestException as e:
            print(f"请求发生错误:{e}")
            return None

    4. 解析HTML并提取数据(核心)

            在使用 requests 获取 HTML 内容后,我们需要使用 BeautifulSoup 将 HTML 文本解析为可操作的树结构,我们将主要使用 BeautifulSoup 的 find_all 和 find 功能实现。find_all 用于查找所有符合条件的 HTML 标签,并返回一个列表;find 用于查找第一个符合条件的 HTML 标签。

            首先,将获取到的 HTML 文档解析成 BeautifulSoup 对象,以便于操作和提取数据。html.parser 是 Python 内置的解析器,适合处理简单的 HTML 页面。如果处理复杂页面,也可使用 lxml 或 html5lib。

    soup = BeautifulSoup(html, 'html.parser')

            其次,我们将定位电影容器。使用 find_all 来查找 HTML 页面中所有 class = "item" 的 div 标签(这些标签包含电影的标题、评分等信息),返回一个包含所有匹配标签的列表,并将其储存在一个空列表 data 中。

    movies = soup.find_all('div', class_='item')
    
    data = []

            之后,我们需要遍历每部电影并提取数据,提取我们需要的电影标题、评分、评价人数、电影简介、电影链接,将其存储为字典并添加到列表,并返回提取的数据。在本部分,我们同样需要使用 except AttributeError as e 进行错误处理。

    for movie in movies:
        try:
            title = movie.find('span', class_='title').text
            rating = movie.find('span', class_='rating_num').text
            comments = movie.find('div', class_='star').find_all('span')[-1].text
            link = movie.find('a')['href']
            intro = movie.find('span', class_='inq').text if movie.find('span', class_='inq') else "暂无简介"
    
            data.append({
                "电影标题": title,
                "评分": rating,
                "评价人数": comments,
                "简介": intro,
                "链接": link
            })
        except AttributeError as e:
            print(f"解析电影信息出错:{e}")
            continue
    return data
    

            该部分的完整代码如下。

    def parse_html(html):
        soup = BeautifulSoup(html, 'html.parser')
        movies = soup.find_all('div', class_='item')
        data = []
        for movie in movies:
            try:
                title = movie.find('span', class_='title').text
                rating = movie.find('span', class_='rating_num').text
                comments = movie.find('div', class_='star').find_all('span')[-1].text
                link = movie.find('a')['href']
                intro = movie.find('span', class_='inq').text if movie.find('span', class_='inq') else "暂无简介"
    
                data.append({
                    "电影标题": title,
                    "评分": rating,
                    "评价人数": comments,
                    "简介": intro,
                    "链接": link
                })
            except AttributeError as e:
                print(f"解析电影信息出错:{e}")
                continue
        return data
    

    5. 爬取多页数据并保存数据

            在解析HTML并提取数据后,我们将实现一个完整的爬虫,并将数据保存为 CSV 文件,以便后续更好地处理。

            我们将爬取豆瓣数据的主函数名为 scrape_douban_top250。通过观察,我们发现豆瓣电影Top250榜单共有10页。因此采用循环变量 page 和字符串拼接的方式,生成分页URL。调用 get_html 函数通过 HTTP 请求获取网页内容,并调用 parse_html 函数使用 BeautifulSoup 解析 HTML 文档,提取结构化数据,如标题、评分、简介等。

    def scrape_douban_top250():
        base_url = "https://movie.douban.com/top250"
        all_data = []  # 初始化一个空列表,用于存储爬取的电影数据
    
        for page in range(10):  # 每页有 25 部电影,共 10 页
            url = f"{base_url}?start={page * 25}"  # 构造分页 URL
            print(f"正在爬取第 {page + 1} 页...")
    
            # 调用 get_html 函数获取 HTML 文本
            html = get_html(url)
            if html:
                # 调用 parse_html 函数解析 HTML,提取电影数据
                page_data = parse_html(html)
                all_data.extend(page_data)  # 将当前页数据添加到总数据列表
                print(f"第 {page + 1} 页爬取完成,共获取 {len(page_data)} 条数据")
    
                # 为了避免被封,设置每次请求后暂停 1 秒
                time.sleep(1)
        
        return all_data  # 返回所有爬取到的电影数据
    

            之后,我们将爬取到的数据需要以便于分析的格式存储下来,使用 pandas 库,将爬取的数据列表转换成 DataFrame,并导出为CSV文件。

    def save_to_csv(data, filename='douban_top250.csv'):
        # 将数据转换为 pandas DataFrame
        df = pd.DataFrame(data)
        # 保存为 CSV 文件,指定 UTF-8 编码以支持中文
        df.to_csv(filename, index=False, encoding='utf-8-sig')
        print(f"数据已保存到 {filename}")
    

    6. 主程序

            设计并启动主程序,执行爬取函数 scrape_douban_top250,获取所有电影数据,并调用 save_to_csv 将数据保存成CSV文件。在程序结束时,打印“爬取完成”。

    if __name__ == "__main__":
        print("开始爬取豆瓣电影 Top 250...")
        data = scrape_douban_top250()
        save_to_csv(data)
        print("爬取完成!")
    

    7. 实现爬虫的完整代码

    import requests
    from bs4 import BeautifulSoup
    import pandas as pd
    import time
    
    # 获取HTML内容的函数
    def get_html(url):
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
        }
        try:
            response = requests.get(url, headers=headers, timeout=10)
            if response.status_code == 200:
                return response.text
            else:
                print(f"请求失败,状态码:{response.status_code}")
                return None
        except requests.RequestException as e:
            print(f"请求发生错误:{e}")
            return None
    
    # 解析HTML并提取数据
    def parse_html(html):
        soup = BeautifulSoup(html, 'html.parser')
        movies = soup.find_all('div', class_='item')
        data = []
        for movie in movies:
            try:
                title = movie.find('span', class_='title').text
                rating = movie.find('span', class_='rating_num').text
                comments = movie.find('div', class_='star').find_all('span')[-1].text
                link = movie.find('a')['href']
                intro = movie.find('span', class_='inq').text if movie.find('span', class_='inq') else "暂无简介"
    
                data.append({
                    "电影标题": title,
                    "评分": rating,
                    "评价人数": comments,
                    "简介": intro,
                    "链接": link
                })
            except AttributeError as e:
                print(f"解析电影信息出错:{e}")
                continue
        return data
    
    # 爬取多页数据
    def scrape_douban_top250():
        base_url = "https://movie.douban.com/top250"
        all_data = []
        for page in range(10):  # 每页 25 部电影,共 10 页
            url = f"{base_url}?start={page * 25}"
            print(f"正在爬取第 {page + 1} 页...")
            html = get_html(url)
            if html:
                page_data = parse_html(html)
                all_data.extend(page_data)
                print(f"第 {page + 1} 页爬取完成,共获取 {len(page_data)} 条数据")
                time.sleep(1)  # 控制请求频率
        return all_data
    
    # 保存数据到CSV文件
    def save_to_csv(data, filename='douban_top250.csv'):
        df = pd.DataFrame(data)
        df.to_csv(filename, index=False, encoding='utf-8-sig')
        print(f"数据已保存到 {filename}")
    
    # 主程序
    if __name__ == "__main__":
        print("开始爬取豆瓣电影 Top 250...")
        data = scrape_douban_top250()
        save_to_csv(data)
        print("爬取完成!")
    

    作者:apwangzitong

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【Python】– 使用BeautifulSoup爬取豆瓣电影Top250榜单

    发表回复