如何使用 Python 搜刮 IMDB 数据

评论: 0

在当今世界,从 IMDB 等在线社交平台中提取数据是收集研究或欣赏所需的电影相关信息的有效途径。在本教程中,我们将使用 Python 浏览 IMDB 上的前 250 部电影,并提取电影标题、电影摘要、评分、流派等详细信息。

在对 IMDB 等网站进行刮擦时,模拟真实用户的行为至关重要,这样可以最大限度地降低被发现的风险,并确保成功检索数据。以下是一些可以采用的策略:

  1. 避免 IP 屏蔽:网站通常会限制从一个 IP 地址发出的请求数量,以防止刮擦。通过使用代理,您可以将请求分散到多个 IP 地址,从而降低被屏蔽的风险。
  2. 确保匿名性:代理服务器会屏蔽你的真实 IP 地址,这不仅有助于保护你的隐私,还能让网站更难追踪到你的刮擦活动。
  3. 遵守速度限制:通过多个代理分配请求有助于管理查询频率,保持在网站的速度限制范围内,降低触发反搜索措施的可能性。
  4. 绕过服务器的怀疑:加入模仿典型浏览器的标头(如 User-Agent),可以让你的刮擦请求看起来更像正常的用户请求。这可以防止服务器将你的活动标记为可疑活动。

步骤 1:准备刮刀

在本教程中,我们将使用 Python 的 requests 库下载网页内容,使用 lxml 解析 HTML,并在需要时使用 json 库处理格式化数据。首先,安装所需的库。

安装程序库

开始之前,您需要安装必要的 Python 库。在终端运行以下命令安装它们:


pip install requests lxml

这些库将用于发出 HTTP 请求、解析 HTML 内容和处理提取的数据。

配置 HTTP 请求标头

要使我们的请求与真正的网络浏览器的请求相似,关键是要相应地设置 HTTP 头信息。下面举例说明如何在脚本中配置这些标头:


import requests

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',  # 请勿追踪标题
    'pragma': 'no-cache',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}

response = requests.get('https://www.imdb.com/chart/top/', headers=headers)

设置代理

代理对于大规模搜索非常有用。它们可以将您的请求分发到多个 IP,从而帮助您避免被拦截。下面介绍了如何使用代理:


proxies = {
    "http": "http://your_proxy_server",
    "https": "https://your_proxy_server"
}

response = requests.get('https://www.imdb.com/chart/top/', headers=headers, proxies=proxies)

将 "your_proxy_server "替换为您可以访问的实际代理详细信息。这样可以确保您的 IP 地址不被暴露,并有助于避免被拦截。

第 2 步:解析 HTML 内容

获取网页内容后,我们需要对其进行解析以提取电影细节。我们将使用 lxml 来解析 HTML,使用 json 来处理结构化数据:


from lxml.html import fromstring
import json

# 解析 HTML 响应
parser = fromstring(response.text)

# 从脚本标签中提取 JSON-LD 数据(结构化数据
raw_data = parser.xpath('//script[@type="application/ld+json"]/text()')[0]
json_data = json.loads(raw_data)

# 现在我们有了 JSON 格式的结构化电影数据

步骤 3:提取电影细节

IMDB Top 250 页面包含嵌入在 HTML 中的结构化数据,可以使用 XPath 轻松访问并解析为 JSON。我们将提取电影的详细信息,如名称、描述、评分、流派等:


movies_details = json_data.get('itemListElement')

# 循环播放影片数据
movies_data = []
for movie in movies_details:
    movie_type = movie['item']['@type']
    url = movie['item']['url']
    name = movie['item']['name']
    description = movie['item']['description']
    image = movie['item']['image']
    bestRating = movie['item']['aggregateRating']['bestRating']
    worstRating = movie['item']['aggregateRating']['worstRating']
    ratingValue = movie['item']['aggregateRating']['ratingValue']
    ratingCount = movie['item']['aggregateRating']['ratingCount']
    contentRating = movie['item'].get('contentRating')
    genre = movie['item']['genre']
    duration = movie['item']['duration']
    
    # 将每部电影的数据添加到列表中
    movies_data.append({
        'movie_type': movie_type,
        'url': url,
        'name': name,
        'description': description,
        'image': image,
        'bestRating': bestRating,
        'worstRating': worstRating,
        'ratingValue': ratingValue,
        'ratingCount': ratingCount,
        'contentRating': contentRating,
        'genre': genre,
        'duration': duration
    })

步骤 4:存储数据

提取数据后,必须将其存储为便于分析的格式。在本例中,我们将使用 pandas 库将其保存为 CSV 文件:


import pandas as pd

# 将电影列表转换为 pandas DataFrame
df = pd.DataFrame(movies_data)

# 将数据保存为 CSV 文件
df.to_csv('imdb_top_250_movies.csv', index=False)

print("IMDB Top 250 movies data saved to imdb_top_250_movies.csv")

完整代码

以下是用于搜索 IMDB 250 大电影的完整代码:


import requests
from lxml.html import fromstring
import json
import pandas as pd

# 为请求定义标头
headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'accept-language': 'en-IN,en;q=0.9',
    'cache-control': 'no-cache',
    'dnt': '1',
    'pragma': 'no-cache',
    'sec-ch-ua': '"Google Chrome";v="129", "Not=A?Brand";v="8", "Chromium";v="129"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Linux"',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'none',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36',
}

# 可选择设置代理
proxies = {
    "http": "http://your_proxy_server",
    "https": "https://your_proxy_server"
}

# 将请求发送至 IMDB 250 强页面
response = requests.get('https://www.imdb.com/chart/top/', headers=headers, proxies=proxies)

# 解析 HTML 响应
parser = fromstring(response.text)

# 提取 JSON-LD 数据
raw_data = parser.xpath('//script[@type="application/ld+json"]/text()')[0]
json_data = json.loads(raw_data)

# 提取电影详细信息
movies_details = json_data.get('itemListElement')

movies_data = []
for movie in movies_details:
    movie_type = movie['item']['@type']
    url = movie['item']['url']
    name = movie['item']['name']
    description = movie['item']['description']
    image = movie['item']['image']
    bestRating = movie['item']['aggregateRating']['bestRating']
    worstRating = movie['item']['aggregateRating']['worstRating']
    ratingValue = movie['item']['aggregateRating']['ratingValue']
    ratingCount = movie['item']['aggregateRating']['ratingCount']
    contentRating = movie['item'].get('contentRating')
    genre = movie['item']['genre']
    duration = movie['item']['duration']
    
    movies_data.append({
        'movie_type': movie_type,
        'url': url,
        'name': name,
        'description': description,
        'image': image,
        'bestRating': bestRating,
        'worstRating': worstRating,
        'ratingValue': ratingValue,
        'ratingCount': ratingCount,
        'contentRating': contentRating,
        'genre': genre,
        'duration': duration
    })

# 将数据保存为 CSV 文件
df = pd.DataFrame(movies_data)
df.to_csv('imdb_top_250_movies.csv', index=False)
print("IMDB Top 250 movies data saved to imdb_top_250_movies.csv")

伦理方面的考虑

在搜索任何网站之前,必须考虑道德和法律问题:

  • 尊重 Robots.txt:检查 IMDB 的 robots.txt 文件,查看允许对网站的哪些部分进行搜刮。始终遵守网站政策。
  • 避免服务器超载:负责任地抓取数据,限制请求频率,避免给服务器带来不必要的负担。
  • 尊重服务条款:确保刮擦不违反 IMDB 的服务条款。

请始终牢记相关规则,将网络搜索用于合法目的。

评论:

0 评论