一 爬虫

爬虫,也称为网络爬虫(网络机器人),是一种按照一定的预设规则,自动浏览并抓取网络数据的程序或脚本。

在这里插入图片描述

使用场景:

  • 搜索引擎(百度、Google)
  • 舆情监控
  • 商业分析(电商比价系统)
  • AI大模型训练语料
  • ……

二 网络机器人-入门

2.1 概述

网络机器人:也称为网络爬虫,是一种按照一定的预设规则,自动浏览并抓取网络数据的程序或脚本。

在这里插入图片描述

数据清洗:是指对采集到的原始数据进行处理、 修正、转换和标准化的过程,目的是让数据变得规范、准确 。

2.1 合规性(robots协议)

robots协议也称为爬虫协议、爬虫规则,是指网站根目录下存放的一份文本文件robots.txt,用于告诉爬虫哪些页面可以抓取,哪些页面不能抓取。(君子协议)

在这里插入图片描述

  • User-Agent:用户代理,通过该请求头确认爬虫的类型
  • Disallow:禁止访问的资源
  • Allow:允许访问的资源
  • Sitemap:网站地图,帮助爬虫更高效地获取网站内容
  • Crawl-delay:爬取间隔时间,避免频繁访问造成网站压力过大

请务必遵守robots君子协定

如百度官网的robots内容如下:https://www.baidu.com/robots.txt

User-agent: Baiduspider
Disallow: /baidu
Disallow: /s?
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Googlebot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: MSNBot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Baiduspider-image
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: YoudaoBot
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou web spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou inst spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou spider2
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou blog
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou News Spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sogou Orion spider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: ChinasoSpider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: Sosospider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh


User-agent: yisouspider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: EasouSpider
Disallow: /baidu
Disallow: /s?
Disallow: /shifen/
Disallow: /homepage/
Disallow: /cpro
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh

User-agent: *
Disallow: /

2.2 入门程序

需求:获取TIOBE编程语言排行榜单,官网 https://www.tiobe.com

点击右上角TIOBE Index

在这里插入图片描述

下拉,可以看到编程语言最新排行榜

在这里插入图片描述

查看官网的robots文件:https://www.tiobe.com/robots.txt

在这里插入图片描述

可以看到,编程语言排行榜的页面没有禁止抓取,所以我们可以进行爬取数据

实现步骤

  1. 查看TIOBE网站的robots.txt文件,明确资源获取的规则
  2. 安装requests库,用于发送网络请求 (pip install requests)
  3. 编写python代码,访问TIOBE网站,获取数据

在这里插入图片描述

Requests库的作用是什么?

Requests库是Python中最流行、最优雅的HTTP客户端库,让Python代码发送HTTP请求变得极其简单

在这里插入图片描述

import requests

# 定义url
target_url = "https://www.tiobe.com/tiobe-index/"

# 发送请求, 获取数据
response = requests.get(target_url)

# 输出数据到控制台(获取到的是前端页面代码,html格式)
print(response.text)

结果

<!DOCTYPE html>
<html lang="en-US">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        	<title>TIOBE Index - TIOBE</title>
	    <link rel="profile" href="http://gmpg.org/xfn/11" />
    <link rel="stylesheet" href="https://www.tiobe.com/wp-content/themes/tiobe/style.css" type="text/css" media="screen" />
    <link rel="pingback" href="https://www.tiobe.com/xmlrpc.php" />

    <link rel="apple-touch-icon" sizes="180x180" href="https://www.tiobe.com/wp-content/themes/tiobe/favicon/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="https://www.tiobe.com/wp-content/themes/tiobe/favicon/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="https://www.tiobe.com/wp-content/themes/tiobe/favicon/favicon-16x16.png">
    <link rel="manifest" href="https://www.tiobe.com/wp-content/themes/tiobe/favicon/site.webmanifest">
    <link rel="mask-icon" href="https://www.tiobe.com/wp-content/themes/tiobe/favicon/safari-pinned-tab.svg" color="#287ac8">
    <link rel="shortcut icon" href="https://www.tiobe.com/wp-content/themes/tiobe/favicon/favicon.ico">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-config" content="https://www.tiobe.com/wp-content/themes/tiobe/favicon/browserconfig.xml">
    <meta name="theme-color" content="#ffffff">

	<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
	<!--[if lt IE 9]>
	<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
	<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
	<![endif]-->
	
		
    <script type="text/javascript">
	window.dataLayer = window.dataLayer || [];

	function gtag() {
		dataLayer.push(arguments);
	}

	gtag("consent", "default", {
		ad_personalization: "denied",
		ad_storage: "denied",
		ad_user_data: "denied",
		analytics_storage: "denied",
		functionality_storage: "denied",
		personalization_storage: "denied",
		security_storage: "granted",
		wait_for_update: 500,
	});
	gtag("set", "ads_data_redaction", true);
	</script>
<script type="text/javascript">
		(function (w, d, s, l, i) {
		w[l] = w[l] || [];
		w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
		var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l !== 'dataLayer' ? '&l=' + l : '';
		j.async = true;
		j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
		f.parentNode.insertBefore(j, f);
	})(
		window,
		document,
		'script',
		'dataLayer',
		'GTM-P5LV767'
	);
</script>

。。。。。。。。。。。

我们目前获取到的是页面html代码,后期需要对这些html代码进行解析,最终只要我们需要的排行榜数据。

2.3 网页结构

在这里插入图片描述

一个网页是由三个部分组成的,分别是:HTML、CSS、JS(JavaScript)。

  • HTML:超文本标记语言,由一堆预设的标签(<h1>一级标题</h1>)构成。HTML负责网页的结构(页面元素和内容)
  • CSS:层叠样式表。CSS负责网页的表现(页面元素的外观、位置等样式,如颜色、大小等)
  • JS:全称为JavaScript,简称JS。负责网页的行为(交互效果)

在这里插入图片描述

其中,我们主要解析的是html里包裹的内容(数据),css和js我们不关心

HTML(HyperText Markup Language):超文本标记语言。

  • 超文本:超越了文本的限制,比普通文本更强大。除了文字信息,还可以定义图片、音频、视频等内容。
  • 标记语言:由标签 "<标签名>" 构成的语言
    • HTML标签都是预定义好的。例如:使用<h1>展示标题,使用<img>展示图片,使用<video>展示视频。
    • HTML代码直接在浏览器中运行,HTML标签由浏览器解析。

在这里插入图片描述

2.4 网页解析

网页解析指的是从原始HTML文档中提取数据的过程,也是网络爬虫的关键步骤,从一堆标签文本中提取出需要的数据。

在这里插入图片描述

  • lxml:是一个高性能的HTML/XML文档的解析库,支持基于Xpath语法来解析和获取网页数据。
  • 安装:pip install lxml

html示例如下:

..................

<!-- 表格展示区 -->
    <div class="table-container">
      <table>
        <thead>
          <tr>
            <th>姓名</th>
            <th>性别</th>
            <th>头像</th>
            <th>修为</th>
            <th>技能</th>
            <th>身份地位</th>
            <th>师承</th>
            <th>法宝</th>
          </tr>
        </thead>

        <tbody>
          <tr>
            <td>王林</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="王林"></td>
            <td>婴变期</td>
            <td>罗天传承、三式神通</td>
            <td>天逆弟子</td>
            <td>罗天、天运子</td>
            <td>天劫剑、朱雀印</td>
          </tr>
          <tr>
            <td>李慕婉</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="李慕婉"></td>
            <td>元婴期</td>
            <td>冰系神通、寒气凝霜</td>
            <td>天逆宗长老</td>
            <td>家族传承</td>
            <td>寒冰玉镯、雪蚕丝袍</td>
          </tr>
          <tr>
            <td>王卓</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="王卓"></td>
            <td>金丹期</td>
            <td>剑修之道、御剑术</td>
            <td>天逆宗弟子</td>
            <td>天逆宗</td>
            <td>青锋剑、金鳞甲</td>
          </tr>
          <tr>
            <td>柳眉</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="柳眉"></td>
            <td>筑基后期</td>
            <td>幻境迷心、魅惑之术</td>
            <td>云天宗弟子</td>
            <td>云天宗</td>
            <td>迷魂幡、幻影纱</td>
          </tr>
          <tr>
            <td>张虎</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="张虎"></td>
            <td>结丹期</td>
            <td>大力神功、金刚不坏</td>
            <td>天逆宗弟子</td>
            <td>天逆宗</td>
            <td>虎头战戟、玄铁护心镜</td>
          </tr>
          <tr>
            <td>木冰眉</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="木冰眉"></td>
            <td>化神期</td>
            <td>冰封万里、玄冰掌</td>
            <td>雨之仙域修士</td>
            <td>雨之仙域传承</td>
            <td>玄冰扇、冰晶戒</td>
          </tr>
          <tr>
            <td>司徒南</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="司徒南"></td>
            <td>化神后期</td>
            <td>南宫剑诀、遁甲术</td>
            <td>南宫世家家主</td>
            <td>南宫世家传承</td>
            <td>南宫剑、遁甲符</td>
          </tr>
          <tr>
            <td>天运子</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="天运子"></td>
            <td>问鼎中期</td>
            <td>天运神通、推演之术</td>
            <td>天运宗宗主</td>
            <td>自创天运之道</td>
            <td>天运珠、问鼎印</td>
          </tr>
          <tr>
            <td>云雀子</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="云雀子"></td>
            <td>问鼎后期</td>
            <td>雀羽飞剑、风雷遁</td>
            <td>踏天峰传人</td>
            <td>踏天峰传承</td>
            <td>云雀剑、风雷翼</td>
          </tr>
          <tr>
            <td>罗天星</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="罗天星"></td>
            <td>婴变前期</td>
            <td>星辰之力、星移斗转</td>
            <td>罗天星域守护者</td>
            <td>星辰古神传承</td>
            <td>星河图、星辰链</td>
          </tr>
          <tr>
            <td>藤化元</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="藤化元"></td>
            <td>元婴大圆满</td>
            <td>藤蔓束缚、化神之术</td>
            <td>藤家老祖</td>
            <td>藤家传承</td>
            <td>化神藤鞭、元婴护盾</td>
          </tr>
          <tr>
            <td>孙泰</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="孙泰"></td>
            <td>筑基后期</td>
            <td>沙土遁术、黄沙漫天</td>
            <td>沙家族长</td>
            <td>沙家传承</td>
            <td>黄沙印、遁地符</td>
          </tr>
          <tr>
            <td>墨智</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="墨智"></td>
            <td>化神初期</td>
            <td>悟道意境、墨染虚空</td>
            <td>神秘强者</td>
            <td>自创意境之道</td>
            <td>悟道笔、意境画卷</td>
          </tr>
          <tr>
            <td>十三</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="十三"></td>
            <td>筑基初期</td>
            <td>隐匿追踪、暗杀之术</td>
            <td>神秘杀手</td>
            <td>未知</td>
            <td>暗影匕首、隐身符</td>
          </tr>
          <tr>
            <td>莫厉海</td>
            <td></td>
            <td><img src="https://ai-web-2025.oss-cn-beijing.aliyuncs.com/1.png" alt="莫厉海"></td>
            <td>元婴初期</td>
            <td>烈焰神通、火海无边</td>
            <td>火焚国国主</td>
            <td>火焚国传承</td>
            <td>烈焰刀、火灵珠</td>
          </tr>
        </tbody>
      </table>
    </div>
    
...............

xpath解析上边的html

from lxml import html
# 加载html文件
with open("resources/仙逆人物志.html", "r", encoding="utf-8") as f:
    html_content = f.read()
    doc = html.fromstring(html_content)
    
    # 解析表头:获取html文档里,所有的table下的thead标签下的tr标签下的th标签下的文本,结果会封装到列表里
    th_list = doc.xpath("//table/thead/tr[1]/th/text()")
    print(th_list)
    
    # 解析表格里的数据(tr[1]代表获取第一个tr即可)
    # td_list = doc.xpath("//table/tbody/tr[1]/td/text()")
    # print(td_list)
    
    # 获取所有行(tr)数据
    tr_list = document.xpath("//table/tbody/tr")
    for tr in tr_list:
       td_list = tr.xpath("./td/text()")
       print(td_list)

结果:

在这里插入图片描述

Xpath

Xpath是一种用于在HTML/XML文档中导航或定位元素的查询语言,让你能够准确的定位文档中的特定元素、属性或文本 。

表达式 描述 样例
/ 从根节点的直接子元素 /html/body/div/h1 依次从html下找body、div、h1
// 从任意位置选择节点 //h1
. 当前节点下查找 ./a./a
[n] 选择第 n 个元素 //p[2]
[last()] 选择最后一个元素 //p[last()]
[@attr] 选择有该属性的元素 //p[@color]
[@attr='value'] 选择该属性值等于指定值的元素 //p[@color='red']
* 匹配任何元素节点 //body/div/*
@* 匹配元素的任何属性 //body/div/a/@*
text() 获取文本内容 //div/p/text()
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>仙逆人物志 - 修真世界</title>
</head>
<body>
    <div>
        <h1>Python</h1>
        <p>一门简介、快速、易用的编程语言。</p>
        <p>人生苦短,我用Python。</p>
        <p color="red">AI大模型开发、AI智能应用开发。</p>
        <a href="https://www.itcast.cn">麦芽糖资源站</a>
    </div>
</body>
</html>

我们继续解析编程排行榜网站的html内容

import requests
from lxml import html

# 定义url
target_url = "https://www.tiobe.com/tiobe-index/"

# 发送请求, 获取数据
response = requests.get(target_url)

# 输出数据到控制台(获取到的是前端页面代码,html格式)
#print(response.text)

document = html.fromstring(response.text)

# 解析数据
# 解析表头
# th_list = document.xpath("//table[@id='top20']/thead/tr/th/text()")
# th_list = document.xpath("/html/body/section/div/article/table[1]/thead/tr/th/text()")
th_list = document.xpath("//*[@id='top20']/thead/tr/th/text()")
print(th_list)

# 解析表格中的数据
tr_list = document.xpath("//table[@id='top20']/tbody/tr")
for tr in tr_list:
    td_list = tr.xpath("./td/text()")
    print(td_list)

结果

['Feb 2026', 'Feb 2025', 'Change', 'Programming Language', 'Ratings', 'Change']
['1', '1', 'Python', '21.81%', '-2.08%']
['2', '4', 'C', '11.05%', '+1.22%']
['3', '2', 'C++', '8.55%', '-2.82%']
['4', '3', 'Java', '8.12%', '-2.54%']
['5', '5', 'C#', '6.83%', '+2.71%']
['6', '6', 'JavaScript', '2.92%', '-0.85%']
['7', '10', 'Visual Basic', '2.85%', '+0.81%']
['8', '15', 'R', '2.19%', '+1.14%']
['9', '7', 'SQL', '1.93%', '-0.93%']
['10', '9', 'Delphi/Object Pascal', '1.88%', '-0.29%']
['11', '30', 'Perl', '1.67%', '+1.19%']
['12', '11', 'Fortran', '1.64%', '-0.12%']
['13', '14', 'PHP', '1.34%', '+0.20%']
['14', '13', 'Rust', '1.32%', '-0.14%']
['15', '12', 'Scratch', '1.30%', '-0.25%']
['16', '8', 'Go', '1.23%', '-1.03%']
['17', '24', 'Ada', '1.14%', '+0.43%']
['18', '16', 'MATLAB', '1.13%', '+0.14%']
['19', '17', 'Assembly language', '1.10%', '+0.15%']
['20', '23', 'Kotlin', '1.05%', '+0.29%']

三 网络机器人案例

需求:获取高分电影榜单(Top100)数据,并保存在CSV文件中。数据包括:电影名、年份、上映时间、类型、时长、评分、语言、导演、作者、主演、Slogan、简介。

在这里插入图片描述

3.1 CSV介绍

CSV:(Comma-Separated Values,逗号分隔值),是一种简单、通用的文本文件格式,用于存储表格数据,可以直接使用Excel打开 。

with open("resources/01.csv", "w", encoding="utf-8") as f:
    f.write("姓名,年龄,性别,爱好\n")
    f.write("王林,29,男,'Python,Java'\n")
    f.write("红蝶,18,女,Java\n")
import csv
with open("resources/02.csv", "w", encoding="utf-8", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["姓名", "年龄", "性别", "爱好"])
    writer.writeheader()
    writer.writerow({"姓名": "王林", "年龄": 29, "性别": "男", "爱好": "Python,Java"})
    writer.writerow({"姓名": "红蝶", "年龄": 18, "性别": "女", "爱好": "Java"})

3.2 案例实现

在这里插入图片描述

步骤:

  1. 明确网站(https://www.themoviedb.org)的robots.txt中的抓取规则
  2. 查看页面的结构,拆解具体的操作步骤,按步骤开发
    a. 获取高分电影列表数据
    b. 遍历电影列表,获取每一部电影的详情信息,并提取电影数据信息
    c. 将电影详情信息保存到csv文件

对提取的年份、上映时间、时长的数据处理

在这里插入图片描述

获取电影排行,并存为csv文件

import requests
import csv
from lxml import html


# 常量
MOVIE_LIST_FILE = "csv_data/movie_list.csv"
TMDB_BASE_URL = "https://www.themoviedb.org"
TMDB_TOP_URL_1 = "https://www.themoviedb.org/movie/top-rated" # 高分电影榜单的url(第1页)
TMDB_TOP_URL_2 = "https://www.themoviedb.org/discover/movie/items" # 高分电影榜单的url(第2页之后)

# 保存电影数据, 保存为 csv 文件
def save_all_movies(all_movies):
    with open(MOVIE_LIST_FILE, "w", encoding="utf-8", newline="") as csvfile:
        writer = csv.DictWriter(csvfile, fieldnames=["电影名", "年份", "上映时间", "类型", "时长", "评分", "语言", "导演", "作者", "宣传语", "简介"])
        writer.writeheader() # 写入表头
        writer.writerows(all_movies) # 写入数据


# 获取电影详情
def get_movie_info(movie_info_url):
    # 1. 发送请求, 获取电影详情数据
    movie_response = requests.get(movie_info_url, timeout=60)
    print(f"发送请求{movie_info_url}, 获取电影详情数据 ...")

    # 2. 解析数据, 获取电影详情
    movie_doc = html.fromstring(movie_response.text)

    movie_names = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[1]/h2/a/text()") # 电影名称
    movie_years = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[1]/h2/span/text()") # 上映年份
    movie_dates = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[1]/div/span[@class='release']/text()") # 上映时间
    movie_tags = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[1]/div/span[@class='genres']/a/text()") # 类型
    movie_cost_times = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[1]/div/span[@class='runtime']/text()") # 时长
    movie_scores = movie_doc.xpath("//*[@id='consensus_pill']/div/div[1]/div/div/@data-percent") # 评分
    movie_languages = movie_doc.xpath("//*[@id='media_v4']/div/div/div[2]/div/section/div[1]/div/section[1]/p[3]/text()") # 语言
    movie_directors = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[3]/ol/li[1]/p[1]/a/text()") #  导演
    movie_authors = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[3]/ol/li[2]/p[1]/a/text()") # 作者
    movie_slogans = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[3]/h3[1]/text()") # 宣传语
    movie_descriptions = movie_doc.xpath("//*[@id='original_header']/div[2]/section/div[3]/div/p/text()") # 简介

    # 3. 返回电影详情 - 字典
    movie_info = {
        "电影名": movie_names[0].strip() if movie_names else '',
        "年份": movie_years[0].strip() if movie_years else '',
        "上映时间": movie_dates[0].strip() if movie_dates else '',
        "类型": ",".join(movie_tags) if movie_tags else '',
        "时长": movie_cost_times[0].strip() if movie_cost_times else '',
        "评分": movie_scores[0].strip() if movie_scores else '',
        "语言": movie_languages[0].strip() if movie_languages else '',
        "导演": ",".join(movie_directors) if movie_directors else '',
        "作者": ",".join(movie_authors) if movie_authors else '',
        "宣传语": movie_slogans[0].strip() if movie_slogans else '',
        "简介": movie_descriptions[0].strip() if movie_descriptions else ''
    }
    return movie_info


# 主函数, 定义核心逻辑
def main():
    all_movies = [] # 保存所有的电影数据

    # 循环获取电影列表(第1页到第5页)
    for page_num in range(1, 6):
        # 1.发送请求, 获取高分电影榜单数据
        if page_num == 1:
            response = requests.get(TMDB_TOP_URL_1, timeout=60)
        else:
            response = requests.post(TMDB_TOP_URL_2,
                                     f"air_date.gte=&air_date.lte=&certification=&certification_country=CN&debug=&first_air_date.gte=&first_air_date.lte=&include_adult=false&latest_ceremony.gte=&latest_ceremony.lte=&page={page_num}&primary_release_date.gte=&primary_release_date.lte=&region=&release_date.gte=&release_date.lte=2026-07-31&show_me=everything&sort_by=vote_average.desc&vote_average.gte=0&vote_average.lte=10&vote_count.gte=300&watch_region=CN&with_genres=&with_keywords=&with_networks=&with_origin_country=&with_original_language=&with_watch_monetization_types=&with_watch_providers=&with_release_type=&with_runtime.gte=0&with_runtime.lte=400",
                                     timeout=60)
        print(f"发送请求, 访问第{page_num}页的数据, 获取TMDB电影榜单数据 ...")

        # 2.解析数据, 获取电影列表
        document = html.fromstring(response.text)
        movie_list = document.xpath(f"//*[@id='page_{page_num}']/div[@class='card style_1']")

        # 3.遍历电影列表, 获取电影详情
        for movie in movie_list:
            movie_urls = movie.xpath("./div/div/a/@href")
            if movie_urls:
                # 电影详情的url
                movie_info_url = TMDB_BASE_URL + movie_urls[0]
                # 发送请求, 获取电影详情数据
                movie_info = get_movie_info(movie_info_url)
                all_movies.append(movie_info)

    # 4.保存数据, 保存为 csv 文件
    print("获取到所有的电影详情, 保存电影数据到CSV文件 ...")
    save_all_movies(all_movies)

if __name__ == '__main__':
    main()

正则表达式

正则表达式(Regular Expression)是一种用特定语法规则组成的字符串模式,用来描述、匹配或替换文本中符合某种规则的字符序列,可以理解为是专门用于文本处理的“高级查找和匹配公式”。

字符串前的r标识什么意思?

r表示当前这个字符串中的转义字符无效,作为普通字符串使用

re模块提供的如下三个函数的作用与区别 ?

  • match(“正则表达式”, “文本字符串”):从字符串的开头开始匹配
  • search(“正则表达式”, “文本字符串”):从任意位置开始,搜索第一个匹配项
  • findall(“正则表达式”, “文本字符串”):从任意位置开始,搜索所有匹配项

正则表达式的写法多种多样,具体的语法如下:

表达式 描述
普通字符 字母、数字、汉字及大多数字符,直接匹配自身
. 匹配任意一个字符(除 \n
\d 匹配数字 0-9
\D 匹配非数字
\w 匹配单词字符,即 a-zA-Z0-9_
\W 匹配非单词字符
\s 匹配空白字符,即 空格、\t
\S 匹配非空白字符
* 出现任意次(0次或无数次)
+ 至少出现1次(1次或无数次)
? 至多出现一次(0次或1次)
{m} 出现 m
{m,} 至少出现 m
{m,n} 出现 mn
| 或的意思,匹配左右任意一个表达式
() 将括号中的字符作为一个分组
^ 匹配字符串开头
$ 匹配字符串结尾
Logo

更多推荐