| Day 20 | 第三方库:pip / venv / requests / BeautifulSoup |

1 pip —— 第三方库的「安装管家」

是什么?为什么学?

pip 是 Python 自带的包管理工具,从 PyPI(Python Package Index,Python 官方软件仓库,全球开发者共享代码的地方)下载并安装第三方库。标准库之外的好东西——网页请求、数据分析、图像处理——几乎都靠 pip install 装进环境。标准库是「自带工具箱」,而第三方库是全世界开发者分享的「超级工具箱」。

底层原理

pip install requests 做的事情:① 在 PyPI 仓库里查找名为 requests 的包(同时解析它的依赖,比如它依赖的 urllib3certifi);② 下载对应你 Python 版本的文件(通常是 .whl 轮子格式,即预编译好的安装包);③ 解压到当前环境的 site-packages 目录。关键点:pip 装到「哪个环境」,取决于你用哪个 python 命令——所以稳妥写法是 python -m pip(用当前 python 解释器去调 pip,保证装进同一个环境)。

生活类比

pip 像手机应用商店:PyPI 是商店,pip install 是「点击安装」,pip list 是「已装应用列表」,pip uninstall 是「卸载」。python -m pip 相当于「先确认是这台手机再安装」——避免装错设备。

注意事项总结

1 查看 pip 版本与已安装列表

python -m pip --version
python -m pip list

运行结果(版本号以实际为准):

pip 25.3 from C:\...\site-packages\pip (python 3.14)
Package        Version
------------- ---------
beautifulsoup4 4.15.0 / requests 2.34.2

python -m pip --version 打印 pip 版本(**python -m 保证用的是当前解释器**);pip list 列出当前环境所有已装包。

2 安装 / 查看详情 / 卸载

python -m pip install requests beautifulsoup4      # 安装
python -m pip show requests                        # 查看详情
python -m pip uninstall requests                   # 卸载(会二次确认)

运行结果(安装成功的典型输出片段):

Collecting requests ... Successfully installed requests-2.32.3

3 国内网络慢加镜像源python -m pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

易错点

  • 错误写法:直接敲 pip install requests → 问题:多个 Python 时可能装进别的版本,import 依然报错 → 正确写法:用 python -m pip install 绑定当前解释器。
  • 错误写法:import requestsModuleNotFoundError 却不去装 → 问题:第三方库必须显式安装,不像标准库自带 → 正确写法:先 python -m pip install requests

记忆口诀:pip 是管家,PyPI 是仓库;python -m pip 最稳妥,装完 import 才不慌。

2 虚拟环境 venv —— 每个项目一个「独立房间」

是什么?为什么学?

虚拟环境(virtual environment)是 Python 为每个项目创建的一套独立隔离的解释器 + 库目录。项目 A 需要 requests 2.x、项目 B 需要 requests 1.x,全装全局会互相打架;虚拟环境让每个项目有自己的库,互不影响。团队开发、部署上线时,这是标准操作。

底层原理

python -m venv venv 在当前目录生成 venv 文件夹:一份解释器入口(Windows 是 venv\Scripts\python.exe)+ 独立的 site-packages 目录。激活(venv\Scripts\activate)的本质是修改环境变量 PATH,让 python / pip 优先指向这个文件夹;退出(deactivate)则恢复 PATH。隔离的真相:路径指向不同,装的库各归各家

生活类比

虚拟环境像酒店房间:每个项目住一间,房内物品(依赖库)只属于这间房;退房(deactivate)后互不影响。全局环境像大宿舍,谁都能往里放东西,互相串味。

注意事项总结

1 创建 + 激活 + 退出

python -m venv venv        # 1. 创建虚拟环境(生成 venv 文件夹)
venv\Scripts\activate      # 2. 激活(Windows;macOS/Linux 用 source venv/bin/activate)
pip list                   # 3. 激活后看到的是这个环境自己的包
deactivate                 # 4. 退出环境

运行效果(激活后提示符前出现 (venv)):

(venv) C:\project> pip list
Package    Version
--------- -------
pip        25.3

python -m venv venv 创建隔离环境(只需一次);venv\Scripts\activate 激活后,**提示符前面出现 (venv)**,此时 pip install 装的库只属于这个项目;deactivate 退出回到全局。

2 不激活也能用——直接调 venv 里的 python

venv\Scripts\python.exe -m pip --version

运行结果:pip 25.3 from C:\project\venv\Lib\site-packages\pip (python 3.14) 注意路径里的 venv\Lib\site-packages——这个 pip 属于 venv 自己的目录。不激活时,直接用 venv\Scripts\python.exe 也能享受隔离环境,脚本自动化(定时任务)常用这招。

易错点

  • 错误写法:忘激活就直接 pip install → 问题:装进了全局环境,项目里 import 不到 → 正确写法:先 venv\Scripts\activate 看到 (venv) 再装。
  • 错误写法:把 venv 文件夹提交到 git / 发给别人 → 问题:体积大且含本机绝对路径,换电脑就废 → 正确写法:只提交 requirements.txt,别人 pip install -r 重建。

记忆口诀:一个项目一间房,venv 建好再装库;提示符带 (venv),deactivate 退房。

3 requests —— 用几行代码「访问」网页

是什么?为什么学?

requests 是 Python 最流行的 HTTP 请求库,封装了网络协议细节,让「访问一个网址」变成一行 requests.get(url)。抓网页、调 API(天气、地图、翻译接口)都是发 HTTP 请求,requests 是标配。自己用标准库 urllib 写要处理编码、重定向、超时等一堆细节,requests 全部代劳。

底层原理

requests.get(url) 内部发一次 HTTP GET 请求:建立连接(基于 urllib3)→ 发送请求头 → 服务器返回响应 → 封装成 Response 对象。对象里有:status_code200 成功、404 不存在、403 拒绝)、text(网页文本)、headers(响应头)、encoding(编码)。关键点:网络请求可能失败(断网、超时、被反爬),要用 try/except 包住,别让程序因一次网络抖动崩溃。

生活类比

requests 像打电话requests.get(url) 是「拨号 + 问一句话」,Response 是「对方答复」——先听语气(200 是「好的」,404 是「没这人」),再听内容(resp.text)。

注意事项总结

1 请求网页,看状态码和内容(需要联网):

import requests

resp = requests.get("https://example.com")
print("状态码:", resp.status_code)
print("编码:", resp.encoding)
print("网页文本前 120 字符:")
print(resp.text[:120])

示例输出(联网运行时):

状态码: 200
编码: ISO-8859-1
网页文本前 120 字符: <!doctype html><html lang="en"><head><title>Example Domain...

requests.get(...) 发请求返回响应对象;resp.status_code 判断成功与否;resp.text[:120] 取网页源码前 120 字符——这就是 HTML 字符串,下一步交给 BeautifulSoup 解析。

2 带浏览器标识 + 异常处理(断网也不崩溃)(需要联网):

import requests

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}
try:
    resp = requests.get("https://example.com", headers=headers, timeout=10)
    resp.raise_for_status()          # 状态码非 200 时抛出异常
    print("请求成功,状态码:", resp.status_code)
except requests.RequestException as e:
    print("请求失败:", e)

headers 带上浏览器标识(User-Agent)减少被拒概率;timeout=10 设超时防止无限等待;raise_for_status() 在状态码非 200 时抛异常;except requests.RequestException 接住所有请求类异常(断网、超时、404 都算)——网络不可控,必须兜底

3 中文乱码先查编码resp.encoding = "utf-8"resp.encoding = resp.apparent_encoding(自动推断)。

易错点

  • 错误写法:不写 timeout → 问题:服务器不响应时程序无限卡住 → 正确写法:requests.get(url, timeout=10)
  • 错误写法:不写 try/except → 问题:断网或超时直接抛异常崩溃 → 正确写法:用 except requests.RequestException 兜底。
  • 错误写法:URL 忘了 https:// → 问题:报 InvalidURL / MissingSchema → 正确写法:URL 写全:https://example.com

记忆口诀:get 是打电话,resp 是答复;200 是成功,404 没人接;超时兜底别忘 try。

4 BeautifulSoup —— 把 HTML 变成「对象树」

是什么?为什么学?

beautifulsoup4(bs4)是解析 HTML/XML 的库。网页源码是一大坨字符串,直接 find / 切片提取非常痛苦;BeautifulSoup 把 HTML 解析成一棵树(标签嵌套结构),然后就能用「找标签」的方式取内容。配合 requests 就是完整的「抓取 + 解析」链路。

底层原理

BeautifulSoup(html, "html.parser") 用解析器把 HTML 字符串变成一棵对象树:每个标签是一个 Tag 对象,标签之间是父子/兄弟关系。然后:soup.h1 取第一个 h1soup.find("p", class_="temp") 按标签 + 属性找、soup.find_all("a")所有 atag.text 取文本、tag["href"] 取属性、soup.select(".news h2") 用 CSS 选择器。**注意 class 是 Python 关键字,所以用 class_**。

生活类比

BeautifulSoup 像档案管理员:HTML 是一堆杂乱的纸(字符串),管理员按目录整理成档案柜(对象树)——找「所有标题」查 find_all("h2"),找「正文第一段」查 find("p"),几秒搞定。

注意事项总结

1 解析本地 HTML 字符串,提取标题/段落/链接(离线可跑):

from bs4 import BeautifulSoup

html = """
<html><body>
<h1>今日天气</h1>
<p class="temp">28 度</p>
<p class="desc">多云转晴</p>
<a href="/detail">查看详情</a>
</body></html>
"""

soup = BeautifulSoup(html, "html.parser")
print("h1 文本:", soup.h1.text)
print("temp:", soup.find("p", class_="temp").text)
print("链接:", soup.a["href"], "|", soup.a.text)

运行结果(离线可复现):

h1 文本: 今日天气
temp: 28 度
链接: /detail | 查看详情

BeautifulSoup(html, "html.parser") 把字符串解析成对象树;soup.h1.text 取第一个 h1 的文本;soup.find("p", class_="temp") 按标签和 class 找(**class_ 带下划线**);soup.a["href"]ahref 属性。

2 find_all 批量提取 + CSS 选择器 + 嵌套表格(离线可跑):

from bs4 import BeautifulSoup

html = """
<ul>
  <li>苹果</li>
  <li>香蕉</li>
  <li>梨</li>
</ul>
<table>
  <tr><th>水果</th><th>价格</th></tr>
  <tr><td>苹果</td><td>5.5</td></tr>
  <tr><td>香蕉</td><td>3.0</td></tr>
</table>
"""

soup = BeautifulSoup(html, "html.parser")
items = [li.text for li in soup.find_all("li")]      # 列表推导式批量取文本
print("水果:", items)

rows = []
for tr in soup.find_all("tr")[1:]:                   # 跳过表头行
    rows.append([td.text for td in tr.find_all("td")])
print("表格:", rows)
print("CSS 选择器:", [h.text for h in soup.select("th")])

运行结果(离线可复现):

水果: ['苹果', '香蕉', '梨']
表格: [['苹果', '5.5'], ['香蕉', '3.0']]
CSS 选择器: ['水果', '价格']

soup.find_all("li") 配合列表推导式一次取全部文本——「批量提取」就是 find_all + 推导式soup.find_all("tr")[1:] 跳过表头再逐行取 td,这是解析表格的标准套路(先取行再取格)。

3 requests + bs4 组合——完整「抓取 + 解析」链路(需要联网):

import requests
from bs4 import BeautifulSoup

resp = requests.get("https://example.com")
soup = BeautifulSoup(resp.text, "html.parser")

print("页面标题:", soup.title.string)
for a in soup.find_all("a"):
    print("  ", a.get("href"), "->", a.text)

易错点

  • 错误写法:soup.find("p", class="temp") → 问题:class 是 Python 关键字,语法报错 → 正确写法:用 class_="temp"
  • 错误写法:soup.find(...) 没找到就直接 .text → 问题:返回 NoneNone.textAttributeError → 正确写法:先判断 if tag is not None:
  • 错误写法:忘了 html.parser 参数:BeautifulSoup(html) → 问题:告警「未指定解析器」,行为不确定 → 正确写法:显式写 BeautifulSoup(html, "html.parser")

记忆口诀:BeautifulSoup 建档案,find 一个 find_all 一堆;class 加下划线,text 取文本,None 要先判断。

5 动手实践:请求并解析一个网页

做一个「网页信息提取器」:请求 example.com,提取标题、正文第一段、所有链接,并把链接整理后打印出来。

# page_parser.py —— 请求并解析一个网页
import requests
from bs4 import BeautifulSoup


def fetch_page(url):
    """请求网页,返回 BeautifulSoup 对象;失败返回 None"""
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()     # 状态码非 200 时抛异常
        resp.encoding = "utf-8"
        return BeautifulSoup(resp.text, "html.parser")
    except requests.RequestException as e:
        print("请求失败:", e)
        return None


def show_page_info(url):
    soup = fetch_page(url)
    if soup is None:
        return

    print("=== 页面标题 ===")
    print(soup.title.string if soup.title else "(无标题)")

    print("\n=== 正文第一段 ===")
    p = soup.find("p")
    print(p.text if p else "(无段落)")

    print("\n=== 页面里的链接 ===")
    links = soup.find_all("a")
    for i, a in enumerate(links, 1):
        href = a.get("href")
        text = a.text.strip()
        print(f"{i}. {href} -> {text}")
    print(f"\n共找到 {len(links)} 个链接")


if __name__ == "__main__":
    show_page_info("https://example.com")

示例输出(需要联网运行;页面内容如有微调不影响理解结构):

=== 页面标题 ===
Example Domain
=== 正文第一段 ===
This domain is for use in documentation examples without needing permission.
=== 页面里的链接 ===
1. https://iana.org/domains/example -> Learn more
共找到 1 个链接

example.com 是 IANA 提供的稳定测试页面,内容几乎不变,最适合拿来练习。

升级挑战:把提取结果保存到 page_info.txt 文件(用到 Day 13 学的文件写入);再试试请求一个你常逛的公开网页,把标题和所有链接提取出来。注意别频繁请求别人网站,练习用 example.com 最合适。

今日总结

python -m pip install 装库,pip list / show / uninstall 管理,镜像源加速;python -m pip 最稳妥 虚拟环境:python -m venv venv + 激活((venv) 提示符)+ deactivate,项目独立房间 requests.get() 返回 Response:status_code / text / encoding / headers 网络三件套:headers 带 User-Agent、timeout 设超时、try/except 兜底 BeautifulSoup 对象树:soup.h1 / find / find_all / tag.text / tag["href"] / select 解析套路:批量提取 = find_all + 推导式;表格 = 先取行再取格;完整链路 = requests 抓 → bs4 解析 区分联网示例与离线示例:解析类用本地 HTML 字符串离线跑,抓取类才需联网

报错原因修复
ModuleNotFoundError: No module named 'requests'库没安装,或装到了别的环境pip install requests beautifulsoup4,并确认在正确的虚拟环境里
requests.exceptions.ConnectionError网络不通或网址拼错检查网络,确认 URL 完整(含 https://
404 Client Error / 403 Client Error页面不存在,或服务器拒绝访问检查 URL;加上 headers={"User-Agent": "Mozilla/5.0 ..."} 再试
ValueError: Invalid URLURL 写错了补全协议头,如 https://example.com
AttributeError: 'NoneType' object has no attribute 'text'find / soup.a 没找到元素,返回了 None先判断 if tag is not None,或改用 find_all 确认选择器是否正确
页面中文乱码编码判断错误设置 resp.encoding = "utf-8"resp.encoding = resp.apparent_encoding
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇