【Python网络爬虫案例】python爬虫之爬取豆瓣电影信息

🔗 运行环境:PYTHON

🚩 撰写作者:左手の明天

🥇 精选专栏:《python》

🔥  推荐专栏:《算法研究》

#### 防伪水印——左手の明天 ####

💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗

💗今天更新系列【python网络爬虫案例】—— 爬取豆瓣电影信息💗

📆  最近更新:2024 年 08 月 04 日,左手の明天的第 344 篇原创博客

📚 更新于专栏:python网络爬虫

#### 防伪水印——左手の明天 ####


在互联网时代,信息获取变得越来越便捷。如果对电影信息感兴趣,那么可以通过Python编程语言来爬取豆瓣电影的相关信息。下面将介绍如何使用Python爬取豆瓣电影信息的步骤。

一、前言

豆瓣是一个电影资讯网站,用户可以在网站上查找电影信息、评论电影等。我们希望通过爬虫程序获取豆瓣电影的名称、评分和简介等信息,以便进行数据分析或制作推荐系统。

在Python中爬取豆瓣电影信息,我们可以使用多种库,比如requests来发送HTTP请求,以及BeautifulSouplxml来解析HTML内容。但是,需要注意的是,豆瓣网站有反爬虫机制,频繁请求可能会被封IP。因此,在编写爬虫时应当注意请求频率,适当添加请求头,以及考虑使用代理。 

二、基本开发环境

Python 3.9

Pycharm

三、相关模块的使用

  1. from bs4 import BeautifulSoup # 网页解析,获取数据

  2. import re # 正则表达式,进行文字匹配

  3. import Ch  # 自定义模块,提供网络请求和缓存目录获取功能

  4. import requests # 网络

  5. import csv # 数据交换模式,它使用逗号作为字段之间的分隔符,并以纯文本形式存储表格数据。

二、爬取豆瓣电影信息方法

2.1 明确需求

爬取豆瓣Top250排行电影信息,涉及信息包含如下:

1、电影详情;2、电影图片;3、电影名字;4、导演、主演;5、年份、国家、类型;6、评分、评价人数;7、电影简介

下面是展示几种方法展示如何使用爬取豆瓣电影Top 250的信息:

2.2 使用requests和BeautifulSoup库进行爬取

(1)爬取步骤

•使用Python的Requests库发送HTTP请求获取豆瓣电影网页的HTML源码。

•使用BeautifulSoup库解析HTML源码,提取电影名称、评分和简介等信息。

•使用数据库或文件存储提取的电影信息,以便后续使用或分析。

(2) 安装所需库

在Python中,可以使用requests库来发送HTTP请求,使用BeautifulSoup库来解析HTML页面。因此,需要先安装这两个库:

pip install requests beautifulsoup4

(3)爬取代码

# 导入必要的模块
import csv
from bs4 import BeautifulSoup
import Ch  # 自定义模块,提供网络请求和缓存目录获取功能
 
# 主函数
def main(url):
    # 使用Ch模块的get_web_request方法获取网页的HTML内容
    html = Ch.get_web_request(url)
    # 创建BeautifulSoup对象,用于解析HTML
    soup = BeautifulSoup(html, 'html.parser')
    # 获取页面上的每个.item元素(代表每部电影)
    for element in soup.select('.item'):
        # 获取排行榜的序号
        num = element.select_one('em').text
        # 获取电影名称
        zw_name = element.select_one('span.title').text
        # 获取电影详情链接
        urls = element.select_one('div.hd a')['href']
        # 获取评分
        star_rating = element.select('div.star span')[1].text
        # 获取评价人数,去除“人评价”文本
        star_num = element.select('div.star span')[3].text.replace('人评价', '')
        # 获取剧情评语,如果不存在则为空字符串
        content = element.select_one('p span.inq').text if element.select_one('p span.inq') is not None else ''
        # 将抓取的数据打包成元组
        tuples = (num, zw_name, urls, star_rating, star_num, content)
        # 将元组写入CSV文件
        csv_writer.writerow(tuples)
        # 打印当前处理的元组信息
        print(tuples)
 
if __name__ == '__main__':
    # 打开CSV文件,写模式,UTF-8编码,去除空行
    with open(Ch.get_dir_cache_to('test.csv'), mode='w', encoding='utf-8', newline='') as f:
        # 创建CSV写入器
        csv_writer = csv.writer(f)
        # 写入表头
        csv_writer.writerow(['序号', '电影名称', '电影详情链接', '评分', '评价人数', '剧情概况'])
        # 循环抓取前10页的数据
        for i in range(10):
            # 调用main函数,传入当前页的URL
            main(f'https://movie.douban.com/top250?start={i * 25}&filter=')
            # 打印完成提示
            print(f'第{i + 1}页爬取完毕.')

2.3 使用XPath进行爬取

使用XPath来爬取豆瓣电影排行榜是一个常见且有效的方法,因为XPath提供了一种强大的方式来在XML和HTML文档中查找信息。

在Python中,可以结合使用requests库来发送HTTP请求获取网页内容,以及lxmlBeautifulSoup库(尽管BeautifulSoup本身不直接支持XPath,但可以与lxml解析器一起使用以支持XPath)来解析HTML并应用XPath表达式提取所需的数据。

以下是一个使用requestslxml(通过etree模块)来爬取豆瓣电影Top 250排行榜的简单示例:

import requests
from lxml import etree
 
def get_douban_top_movies(url, page=1):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
    }
 
    try:
        response = requests.get(url.format(page), headers=headers)
        response.raise_for_status()  # 如果响应状态码不是200,则引发HTTPError异常
 
        # 使用lxml的etree解析HTML
        html = etree.HTML(response.text)
 
        # XPath表达式用于查找电影列表中的每个电影项
        movie_items = html.xpath('//div[@class="item"]')
 
        movie_list = []
        for item in movie_items:
            title = item.xpath('.//span[@class="title"]/text()')[0].strip()
            info = item.xpath('.//div[@class="bd"]/p/text()')[0].strip()
            rating, num_ratings = map(lambda x: x.strip(), info.split('/', 1))
            try:
                quote = item.xpath('.//span[@class="inq"]/text()')[0].strip()
            except IndexError:
                quote = ''
 
            movie_list.append({
                'title': title,
                'rating': rating,
                'num_ratings': num_ratings,
                'quote': quote
            })
 
        return movie_list
    except requests.RequestException as e:
        print(e)
        return []
 
if __name__ == '__main__':
    url = 'https://movie.douban.com/top250?start={}&filter='
    for page in range(0, 250, 25):  # 豆瓣Top 250是分页的,每页25部电影
        movies = get_douban_top_movies(url, page)
        for movie in movies:
            print(movie)
        # 根据需要,可以在这里添加将数据保存到文件或数据库的逻辑

注意

  1. 上述代码中的XPath表达式//div[@class="item"]是用来查找每部电影的容器元素。这个XPath假设豆瓣的HTML结构是这样的,但实际上这个结构可能会随着时间的推移而改变。

  2. 豆瓣网站有反爬虫措施,频繁请求可能会被封IP。因此,在实际应用中,你应该考虑添加请求间隔(例如使用time.sleep()),使用代理等策略。

  3. 示例中的url.format(page)用于构建分页的URL。豆瓣Top 250每页显示25部电影,所以你可以通过改变start参数的值来遍历所有页面。

  4. 根据豆瓣的当前布局,我使用了XPath .//span[@class="title"]/text() 来提取电影标题,.//div[@class="bd"]/p/text() 来提取评分和评分人数,以及 .//span[@class="inq"]/text()(如果存在)来提取电影简介。然而,随着网站布局的更新,这些XPath表达式可能需要调整。

2.4 使用正则表达式进行爬取

虽然正则表达式(Regular Expressions)在文本处理中非常强大,但它们通常不是解析HTML或XML文档的最佳工具,因为这些文档的结构化特性(如标签和属性)更适合使用如XPath或CSS选择器这样的解析技术。然而,如果你只是需要从一个非常简单的HTML结构或者特定模式的文本中提取数据,或者作为学习的目的,使用正则表达式也是可行的。

对于豆瓣电影排行榜,由于HTML结构相对复杂,直接使用正则表达式可能会变得非常繁琐且易出错。但是,如果我们假设某个特定部分的数据可以通过正则表达式来提取(例如,从某个JavaScript变量中直接提取JSON数据,这在某些情况下可能会发生),我们可以编写一个简化的例子。

然而,在大多数情况下,我们不会直接从HTML标签中提取信息,而是会提取一些更简单的文本模式,比如页面上的某个特定段落或链接的文本。但请注意,对于豆瓣电影排行榜这样的动态内容,数据往往是通过JavaScript动态加载的,因此直接从HTML源代码中可能找不到所有数据。

不过,为了演示如何使用正则表达式来提取一些简单信息(假设这些信息是静态的或者已经以某种方式提取到了文本中),我们可以编写一个简化的Python脚本。但请注意,这个脚本不会直接爬取豆瓣电影排行榜,因为它不会处理JavaScript加载的数据。

import re
 
# 假设这是从某处获取的HTML页面内容(实际上你需要使用requests库来获取它)
# 这里我们使用一个简化的字符串来模拟HTML内容
html_content = '''
<div>
    <h2>电影名称1</h2>
    <p>评分: 9.2</p>
    <p>评价人数: 123,456</p>
</div>
<div>
    <h2>电影名称2</h2>
    <p>评分: 8.5</p>
    <p>评价人数: 65,432</p>
</div>
'''
 
# 使用正则表达式提取电影名称、评分和评价人数
pattern = r'<h2>(.*?)</h2>.*?<p>评分: (\d+\.\d+)</p>.*?<p>评价人数: (\d+,\d+)</p>'
matches = re.findall(pattern, html_content, re.DOTALL)
 
for match in matches:
    title, rating, num_ratings = match
    print(f"电影名称: {title.strip()}, 评分: {rating}, 评价人数: {num_ratings}")
 
# 注意:这里的正则表达式和代码只是为了演示目的
# 实际上,对于复杂的HTML文档,你应该使用像BeautifulSoup或lxml这样的库

但请记住,上面的代码示例并不是用来爬取豆瓣电影排行榜的,因为它不会处理JavaScript动态加载的内容,也不会处理豆瓣网站的反爬虫机制。

对于豆瓣电影排行榜的爬取,你通常需要使用像Selenium这样的工具来模拟浏览器行为,或者分析网络请求来找到实际包含电影数据的API接口,并使用requests库来调用这些API。同时,你还需要处理Cookie、User-Agent等HTTP头部信息,以及可能的反爬虫措施。

 爬取的完整代码如下:

# 导入必要的模块
import csv
import re
from bs4 import BeautifulSoup
import Ch  # 假设Ch模块提供了一些自定义功能,如网络请求和文件路径获取
 
# 定义主函数,负责爬取指定URL的网页数据
def main(url):
    # 使用Ch模块的get_web_request方法发送网络请求并获取响应内容
    html = Ch.get_web_request(url)
    # 使用BeautifulSoup解析HTML内容
    soup = BeautifulSoup(html, 'html.parser')
    # 查找所有class为'item'的div标签,即每一部电影的条目
    for item in soup.find_all('div', class_='item'):
        # 使用正则表达式提取电影详情链接
        info_01 = re.findall(re.compile(r'<a href="(.*?)">'), str(item))[0]
        # 提取电影封面图片链接
        info_02 = re.findall(re.compile(r'<img.*src="(.*?)"', re.S), str(item))[0]
        # 提取电影标题(中文名和英文名),可能有两个标题
        title = re.findall(re.compile(r'<span class="title">(.*)</span>'), str(item))
        # 根据标题数量,设置中文名和外文名
        if len(title) == 2:
            info_03 = title[0]  # 中文名
            info_04 = title[1].replace('/', '')  # 英文名,去除斜杠
        else:
            info_03 = title[0]  # 中文名
            info_04 = ' '  # 如果只有一个标题,英文名留空
        # 提取评分
        info_05 = re.findall(re.compile(r'<span class="rating_num" property="v:average">(.*)</span>'), str(item))[0]
        # 提取评价人数
        info_06 = re.findall(re.compile(r'<span>(\d*)人评价</span>'), str(item))[0]
        # 提取剧情概况,可能不存在
        inq = re.findall(re.compile(r'<span class="inq">(.*)</span>'), str(item))
        if len(inq) == 0:
            info_07 = ' '  # 如果没有概况,留空
        else:
            info_07 = inq[0].replace('。', '')  # 去除句点
        # 提取更多信息,如导演、演员等,可能存在换行和斜杠
        bd = re.findall(re.compile(r'<p class="">(.*?)</p>', re.S), str(item))[0]
        # 清理换行符和多余空格
        bd = re.sub('<br(\s+)?/>(\s+)?', '', bd)
        bd = re.sub('/', '', bd)
        info_08 = bd.strip()  # 去除首尾空格
        # 将提取的信息打包成元组
        tuples = (info_01, info_02, info_03, info_04, info_05, info_06, info_07, info_08)
        # 将元组写入CSV文件
        csv_writer.writerow(tuples)
        # 打印当前处理的元组信息
        print(tuples)
 
if __name__ == '__main__':
    # 打开CSV文件,写模式,UTF-8编码,无空行
    with open(Ch.get_dir_cache_to('test.csv'), mode='w', encoding='utf-8', newline='') as f:
        # 创建CSV写入器
        csv_writer = csv.writer(f)
        # 写入表头
        csv_writer.writerow(['电影详情链接', '图片链接', '影片中文名', '影片外国名', '评分', '评价人数', '剧情概况', '相关信息'])
        # 循环爬取10页数据
        for i in range(10):
            # 调用main函数,传入当前页的URL
            main(f'https://movie.douban.com/top250?start={i * 25}&filter=')
            # 打印完成提示
            print(f'第{i + 1}页爬取完毕.')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

左手の明天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值