☰
零基础Python爬虫入门:从HTTP协议到 requests + BeautifulSoup 实战
2026/9/30 13:07:52 网站建设 项目流程

📌 适合人群:完全没有爬虫经验的初学者 🛠️ 涉及工具:Python 3、requests、BeautifulSoup4、浏览器开发者工具 🎯 学习目标:看懂网页本质 → 发送请求 → 解析数据 → 批量爬取


一、爬虫到底是什么?先看大图景

在写任何代码之前,先建立整体认知。所谓网络爬虫,本质上是模拟浏览器向服务器发送请求,获取网页内容,然后从中提取我们想要的数据。

整个流程可以拆成三步(这也是几乎所有爬虫的灵魂框架):

plain

① 获取网页内容 —— 向服务器要数据,服务器把网页"源代码"返回给我们 ↓ ② 解析网页内容 —— 从一大堆 HTML 代码里,精准找到想要的数据 ↓ ③ 存储 / 分析数据 —— 存成表格(Excel/CSV)、做数据分析、画可视化图表

对应到你的学习笔记,就是:获取 → 解析 → 存储分析。


二、前置知识一:HTTP协议(爬虫的地基)

2.1 什么是HTTP

HTTP(Hypertext Transfer Protocol,超文本传输协议)是客户端(浏览器)和服务器之间的请求-响应协议。

你每打开一个网页,背后都在发生一次对话:

浏览器:"服务器你好,我要/movie/top250这个页面的内容" 服务器:"好的,给你(返回网页代码)"

爬虫的第一步,就是用代码代替浏览器去完成这个对话。

2.2 HTTP请求的结构

一个HTTP请求由三部分组成:

(1)请求行
POST /user/info?new_user=true HTTP/1.1
  • POST:请求方法(常见的还有GET)

  • /user/info?new_user=true:资源路径 + 查询参数

  • HTTP/1.1:协议版本(还有 0.9、1.0、2.0 等)

(2)请求头(Headers)
Host: www.example.com User-Agent: curl/7.77.0 Accept: */*

请求头是关于请求的附加信息。其中User-Agent(用户代理)告诉服务器"我是谁"。

⚠️关键点来了:如果不加User-Agent,服务器看到的就是一个"裸奔的程序",很可能直接拒绝你(比如豆瓣会返回418 错误)。解决办法是伪装成浏览器:

headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" }
(3)请求体(Body)

POST请求通常带有数据(比如登录时提交账号密码),格式常见为 JSON:

{ "username": "zhangsan", "email": "zhangsan@example.com" }

2.3 GET 和 POST 的区别(面试高频)

表格

对比项GETPOST
用途获取数据创建/提交数据
场景浏览网页、翻页提交账号、注册表单
参数位置拼在URL里(?key=value)放在请求体里
爬虫常用度⭐⭐⭐⭐⭐⭐⭐

plain

# GET请求:参数直接写在URL上 www.douban.com/movie/top250?start=75&filter=unwatched └─────┬─────┘ 问号后面就是查询参数

2.4 HTTP响应的结构

服务器返回的响应同样由三部分组成:

HTTP/1.1 200 OK ← 状态行 Date: Fri, 27 Jan 2023 02:10:48 GMT Content-Type: text/html; charset=utf-8 ← 响应头 <!DOCTYPE html> <html> <head><title>首页</title></head> <body><h1>Hello World</h1></body> </html> ← 响应体(真正的网页内容)
  • 状态行:协议版本 + 状态码 + 状态消息

  • 响应头:比如Content-Type告诉我们返回内容的格式是text/html

  • 响应体:就是我们要爬的 HTML 源码

2.5 常见状态码(务必背下来)

状态码含义
✅ 200 OK请求成功,最理想
↪️ 301 Moved Permanently资源永久移动到新地址
⚠️ 400 Bad Request客户端请求不能被服务器理解
⚠️ 401 Unauthorized请求未经授权
⚠️ 403 Forbidden服务器拒绝提供服务(反爬常见)
⚠️ 404 Not Found请求的资源不存在
❌ 500 Internal Server Error服务器内部错误
❌ 503 Server Unavailable服务器当前无法处理请求

在代码中用response.status_code查看,用response.ok快速判断是否成功(2xx 返回 True)。


三、前置知识二:HTML网页结构(解析的地图)

3.1 网页三大件

技术作用
HTML定义网页的结构和信息(骨架)
CSS定义网页的样式(皮肤)
JavaScript定义网页的行为和交互逻辑(肌肉)

爬虫主要和 HTML 打交道。

3.2 HTML的基本结构

<html> <body> <h1>这是一个标题</h1> <p>这是一个段落</p> </body> </html>

HTML 由一对一对的标签(tag)组成:<标签名>开始,</标签名>结束。<h1>和<p>是兄弟标签(同级关系)。

3.3 常用标签速查

标签含义
<h1>~<h6>标题(1最大,6最小)
<p>段落
<br>换行
<i>斜体
<u>下划线
<a>链接
<div>区块容器(最常用,页面布局)
<ul>/<ol>/<li>无序列表 / 有序列表 / 列表项
<span>行内容器(常用来包裹小片段文字)
<b>/<strong>加粗
<table>/<tr>/<td>表格 / 表格行(table row)/ 单元格
<thead>/<tbody>表头区 / 表体区

以表格为例,完整结构长这样:

<table> <thead> <tr> <td>表头1</td> <td>表头2</td> </tr> </thead> <tbody> <tr> <td>111</td> <td>222</td> </tr> <tr> <td>333</td> <td>444</td> </tr> </tbody> </table>

💡爬虫提数据的核心思路:数据总是藏在某个标签里,我们要做的就是在 HTML 中找到那个标签,把它"抠"出来。


四、实战第一步:requests库获取网页内容

4.1 安装与导入

pip install requests
import requests

4.2 第一个爬虫:获取books.toscrape.com首页

import requests response = requests.get("http://books.toscrape.com/") if response.ok: print(response.text) else: print("请求失败")

到这一步,你就已经完成了爬虫流程里的第一步——拿到了网页的源代码(一大串HTML文本)。

4.3 response对象的常用属性

response = requests.get("http://books.toscrape.com/") print(response) # 打印响应对象本身 print(response.status_code) # 状态码,200表示成功 print(response.text) # 响应体内容(字符串形式) print(response.headers) # 响应头 print(response.ok) # 是否成功(2xx → True)

4.4 反爬入门:伪装User-Agent

直接爬豆瓣 Top250 会遇到 418("我是茶壶"),说明服务器识破了你:

import requests response = requests.get("https://movie.douban.com/top250") print(response) # <Response [418]> 被识破了!

加 headers 伪装成浏览器:

import requests headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } response = requests.get("https://movie.douban.com/top250", headers=headers) print(response.status_code) # 200,成功! print(response.text)

🔑 记忆口诀:先不加 headers 试试,不行就加 User-Agent;还不行就检查 Cookie、Referer 等。


五、实战第二步:BeautifulSoup解析网页内容

获取到的response.text是一大坨字符串,肉眼找数据是不可能的。我们用BeautifulSoup把它变成一个结构化、可查询的对象。

5.1 安装与导入

pip install beautifulsoup4
from bs4 import BeautifulSoup import requests

5.2 三步走:请求 → 做汤 → 找料

from bs4 import BeautifulSoup import requests # 1. 请求网页 content = requests.get("http://books.toscrape.com/").text # 2. 把字符串"熬成汤"(解析成结构化对象) soup = BeautifulSoup(content, "html.parser")

经过BeautifulSoup处理后,得到的soup对象就拥有了非常多的方法和属性,可以像查字典一样查找标签。

5.3 findAll():批量查找标签

# 按标签名查找:找到所有 <p> 标签 all_prices = soup.findAll("p", attrs={"class": "price_color"}) for price in all_prices: print(price.string[2:])

运行结果:

51.77 53.74 50.10 47.82 54.23 ...

逐行拆解这个方法:

  • soup.findAll("p", attrs={"class": "price_color"}):找到所有class 为price_color的<p>标签,返回一个列表

  • price.string:取标签里的文本内容(如£51.77)

  • [2:]:字符串切片,去掉前2个字符£,留下纯数字

🔑 注意区分:

  • find()→ 找第一个,返回单个对象

  • findAll()→ 找所有,返回列表

5.4 案例:提取书名

在 books.toscrape 上,书名藏在<h3>标签里的<a>标签中:

<h3> <a href="catalogue/a-light-in-the-attic_1000/index.html" title="A Light in the Attic">A Light in the ...</a> </h3>

对应代码:

all_titles = soup.findAll("h3") for title in all_titles: all_links = title.findAll("a") for link in all_links: print(link.string) # 通过string属性拿到标签内的文本

输出:

A Light in the ... Tipping the Velvet Soumission Sharp Objects Sapiens: A Brief History ... ...

💡嵌套查找是很常用的技巧:先找大容器(h3),再在容器内部继续找小标签(a)。

5.5 案例:爬豆瓣Top250电影名

先在浏览器里右键 → 检查(审查元素),找到标题对应的标签:

<span class="title">三傻大闹宝莱坞</span>

对应代码:

import requests from bs4 import BeautifulSoup headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } response = requests.get("https://movie.douban.com/top250", headers=headers) html = response.text soup = BeautifulSoup(html, "html.parser") all_titles = soup.findAll("span", attrs={"class": "title"}) for title in all_titles: title_string = title.string # 豆瓣每部电影有中文名和英文名两个title,用"/"判断过滤 if "/" not in title_string: print(title_string)

这里用了一个细节技巧:if "/" not in title_string——因为每部电影的中文名和英文名都是class="title",通过是否包含/来只保留中文名。


六、实战第三步:翻页爬取全部250部电影

豆瓣Top250每页只有25部,URL规律是:

第1页: https://movie.douban.com/top250?start=0 第2页: https://movie.douban.com/top250?start=25 第3页: https://movie.douban.com/top250?start=50 ...

规律是start每次加 25。用range(0, 250, 25)生成翻页参数:

for start_num in range(0, 250, 25): print(start_num) # 输出: 0, 25, 50, 75, 100, 125, 150, 175, 200, 225

完整代码:

import requests from bs4 import BeautifulSoup headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } for start_num in range(0, 250, 25): response = requests.get( f"https://movie.douban.com/top250?start={start_num}", headers=headers ) html = response.text soup = BeautifulSoup(html, "html.parser") all_titles = soup.findAll("span", attrs={"class": "title"}) for title in all_titles: title_string = title.string if "/" not in title_string: print(title_string)

🛡️善意提醒:实际爬取时建议在循环中加入time.sleep(1~3)降低请求频率,避免对目标网站造成压力。


七、爬虫法律与道德红线(重要!)

笔记里总结的三条底线,必须刻进DNA:

  1. 不要爬取公民隐私数据

  2. 要尊重版权保护的内容

  3. 国家事务、国防建设相关网站绝对不碰

技术层面的注意点:

  • ⚡请求频率不能过高,否则无异于DDoS 攻击(通过给服务器发送海量高频请求,让网站资源被耗尽,无法服务其他正常用户)

  • 🚧网站如果做出明显的反爬限制(如有些内容登录后可看),尊重限制机制,不要强行突破

  • 📄 爬取前查看网站的robots.txt文件(如www.example.com/robots.txt),它声明了允许/禁止爬取的网页路径范围


八、完整知识图谱(复习用)

┌─────────────────────────────────────────┐ │ 爬虫三步走 │ ├──────────────┬──────────────────────────┤ │ ① 获取网页内容 │ requests库 │ │ │ · requests.get(网址) │ │ │ · response.status_code │ │ │ · response.text / .ok │ │ │ · headers伪装User-Agent │ ├──────────────┼──────────────────────────┤ │ ② 解析网页内容 │ BeautifulSoup库 │ │ │ · BeautifulSoup(text, │ │ │ "html.parser") │ │ │ · find() / findAll() │ │ │ · attrs={"class": "..."} │ │ │ · .string 取文本 │ │ │ · 切片 [2:] 清洗数据 │ ├──────────────┼──────────────────────────┤ │ ③ 存储/分析 │ 存CSV/Excel → 数据分析 │ │ │ → 可视化图表 │ └──────────────┴──────────────────────────┘ 底层支撑: HTTP协议(请求行/请求头/请求体;状态行/响应头/响应体) HTML结构(标签、class属性、层级与兄弟关系)

最小可运行模板(背下来,90%的简单爬虫都是它的变体):

import requests from bs4 import BeautifulSoup headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} url = "目标网址" response = requests.get(url, headers=headers) if response.ok: soup = BeautifulSoup(response.text, "html.parser") items = soup.findAll("标签名", attrs={"class": "目标class"}) for item in items: print(item.string) else: print("请求失败:", response.status_code)

九、常见问题速查(FAQ)

Q1:为什么返回418 / 403?服务器识别出你是爬虫。加上headers伪装 User-Agent,必要时补充 Cookie、Referer。

Q2:为什么findAll返回空列表?检查 class 名是否写对(浏览器里右键检查确认);注意有的class有多个值,要用完整字符串匹配。

Q3:price.string报错 NoneType?说明该标签内嵌套了子标签,string无法确定取哪个。改用.get_text()。

Q4:中文乱码?尝试response.encoding = response.apparent_encoding后再取.text。


十、写在最后

零基础学爬虫,其实就两条主线:

网络线:理解HTTP请求-响应 → 用requests发请求解析线:理解HTML标签结构 → 用BeautifulSoup查标签

把这两条线打通,再加一个for循环实现翻页,你就已经具备了爬取绝大多数静态网页的能力。下一步可以进阶学习:数据存储(CSV/Excel/MySQL)、XPath、正则表达式、Selenium动态页面爬取、Scrapy框架。

如果觉得本文对你有帮助,欢迎点赞收藏,复习时直接对照第八节的图谱过一遍即可。评论区欢迎交流爬取中遇到的问题,下期预告:《Python爬虫进阶:数据存储与清洗实战》。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询