「AI Python 系列」第 03 栏 · Python 爬虫实战
全栏 15 篇 · 零成本跟完 🍃
作者:梅雅达编程笔记
首发:CSDN


摘要: 环境搭建其实就三步:装库、学看F12、写第一行爬虫代码。本篇带你安装requests/bs4/lxml等核心库,手把手教你用浏览器F12分析网络请求和页面结构——这是爬虫最重要的技能,没有之一。然后写出第一个爬虫:抓取公开页面标题和正文。最后搞懂GET和POST的区别,知道什么时候该用哪个。


上篇说了爬虫能干啥、不能干啥。今天正式动手。

环境搭起来,第一个爬虫跑起来,你就算入门了。


一、安装必要的库

打开命令行(Windows 用 cmdPowerShell,Mac 用终端),输入:

pip install requests beautifulsoup4 lxml pandas openpyxl drissionpage

装完会看到一堆 Successfully installed xxx,这就对了。
在这里插入图片描述

简单说下每个库是干嘛的:

用途
requests发 HTTP 请求,爬虫的"手"
beautifulsoup4 + lxml解析 HTML,从网页里抠出你要的数据
pandas + openpyxl数据处理和存 Excel
drissionpage浏览器自动化,后面处理动态页面用

今天只用前三个,后面用到再细说。

装完之后,验证一下:

import requests
from bs4 import BeautifulSoup
import pandas as pd

print("环境 OK!")

不报错就说明装好了。
在这里插入图片描述


二、学会用浏览器 F12(这比写代码更重要)

很多新手上来就 requests.get(),结果抓回来一堆乱码或者空数据。

问题出在哪?你没看网页到底返回了什么。

浏览器 F12 开发者工具是爬虫的眼睛。打开方式:

  • Chrome / Edge: 右键 → 检查,或者按 F12
  • Firefox: 右键 → 检查元素,或者按 F12

打开之后,重点看两个 Tab:

Tab 1:Elements(元素)—— 看页面结构

在这里插入图片描述

这个 Tab 显示的是页面的 HTML 源码。你要从网页里抠数据,就得看这里,找到数据在 HTML 里的位置。

比如打开百度首页,你会看到类似这样的结构:

<div id="wrapper">
  <div id="head">
    <div class="head_wrapper">
      <a href="https://www.baidu.com" class="mnav">新闻</a>
      <a href="https://www.hao123.com" class="mnav">hao123</a>
      ...
    </div>
  </div>
</div>

你要抓"新闻"、"hao123"这些链接,就得找它们的标签特征——比如 class="mnav"<a> 标签。

Tab 2:Network(网络)—— 看请求和响应

在这里插入图片描述

这个 Tab 记录浏览器发出的所有请求。你刷新页面,会看到一堆请求列出来。

重点关注:

  • Name: 请求的 URL
  • Status: 状态码,200 是成功,404 是没找到,403 是被拒绝
  • Type: 请求类型,document 是主页面,xhr/fetch 是 Ajax 请求(后面专门讲)
  • Size: 响应大小
  • Time: 耗时
    在这里插入图片描述

点击某一条请求,右边会显示详情:

  • Headers: 请求头和响应头
  • Preview / Response: 响应内容(HTML 或 JSON)
    在这里插入图片描述

爬虫出问题的时候,第一时间看 Network:

  • 请求发出去了没?
  • 状态码是多少?
  • 返回的内容对不对?

90% 的问题都能在这找到答案。


三、第一个爬虫:抓取页面标题和正文

来写一个真正的爬虫。目标:抓取一个公开页面的标题和主要正文内容。

我们用 Python 官方文档的首页做演示:https://docs.python.org/3/

第一步:发请求,拿到 HTML

import requests

url = "https://docs.python.org/3/"
response = requests.get(url)

# 查看状态码
print(f"状态码:{response.status_code}")

# 查看返回的内容(HTML)
html = response.text
print(f"HTML 长度:{len(html)} 字符")
print(html[:500])  # 打印前 500 个字符看看

运行这段代码,你会看到:

状态码:200
HTML 长度:xxxxx 字符
<!DOCTYPE html>...

状态码 200 表示请求成功,response.text 就是返回的 HTML 源码。

第二步:解析 HTML,提取标题和正文

拿到 HTML 之后,要从里面抠出你要的数据。这时候 BeautifulSoup 上场:

from bs4 import BeautifulSoup

# 用 BeautifulSoup 解析 HTML
soup = BeautifulSoup(html, "lxml")

# 提取标题
title = soup.title.string
print(f"页面标题:{title}")

# 提取主要正文内容(Python 文档首页的主要内容在 id="python-documentation" 的 div 里)
main_content = soup.find("div", id="python-documentation")
if main_content:
    # 获取所有段落文本
    paragraphs = main_content.find_all("p")
    for p in paragraphs[:5]:  # 先看前 5 段
        print(p.get_text(strip=True))
else:
    print("未找到主内容区域")

运行结果大概是:

页面标题:3.14.6 Documentation
Welcome! This is the official documentation for Python 3.14.6.
Documentation sections:
Other resources:
Indices, glossary, and search:
...

搞定。你刚写了第一个爬虫。

完整代码

把上面两段合在一起,加上注释:

"""
Day 02 示例代码:抓取 Python 官方文档首页的标题和正文
作者:梅雅达编程笔记
"""
import requests
from bs4 import BeautifulSoup

# 1. 发请求(设置超时时间,防止无限等待)
url = "https://docs.python.org/3/"
try:
    response = requests.get(url, timeout=10)
except requests.exceptions.Timeout:
    print(f"请求超时:{url}")
    exit()
except requests.exceptions.ConnectionError:
    print(f"连接失败:{url}(请检查网络)")
    exit()
except Exception as e:
    print(f"请求异常:{e}")
    exit()

if response.status_code != 200:
    print(f"请求失败,状态码:{response.status_code}")
else:
    # 2. 解析 HTML
    html = response.text
    soup = BeautifulSoup(html, "lxml")
    
    # 3. 提取标题
    title = soup.title.string
    print(f"页面标题:{title}")
    print("-" * 50)
    
    # 4. 提取主内容(页面结构可能变化,使用多种选择器尝试)
    main_content = soup.find("div", class_="body")
    if not main_content:
        main_content = soup.find("main")
    if not main_content:
        main_content = soup.find("div", id="python-documentation")
    
    if main_content:
        paragraphs = main_content.find_all("p")
        print(f"找到 {len(paragraphs)} 个段落,前 5 段内容:")
        print()
        for i, p in enumerate(paragraphs[:5], 1):
            text = p.get_text(strip=True)
            print(f"[段落 {i}] {text}")
    else:
        print("未找到主内容区域")

在这里插入图片描述


四、GET 和 POST:什么时候用哪个

刚才用的是 requests.get(),这是最常见的请求方式。

HTTP 协议有几种请求方法,最常用的是 GET 和 POST:

方法用途例子
GET获取数据打开网页、搜索(参数在 URL 里)
POST提交数据登录、表单提交(参数在请求体里)

GET 请求

你平时浏览网页,99% 都是 GET。你访问一个 URL,服务器返回页面内容。

如果 URL 带参数,长这样:

https://www.baidu.com/s?wd=python

wd=python 就是参数,表示搜索关键词是"python"。

requests 里,GET 请求可以这样传参数(建议加上超时设置):

import requests

params = {"wd": "python"}
try:
    response = requests.get("https://www.baidu.com/s", params=params, timeout=10)
    print(f"GET 请求状态码:{response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"GET 请求失败:{e}")

效果跟直接访问 https://www.baidu.com/s?wd=python 一样。

POST 请求

登录、提交表单的时候,通常用 POST。参数不会出现在 URL 里,而是放在请求体(body)里。

import requests

data = {"username": "test", "password": "123456"}
try:
    response = requests.post("https://example.com/login", data=data, timeout=10)
    print(f"POST 请求状态码:{response.status_code}")
except requests.exceptions.RequestException as e:
    print(f"POST 请求失败:{e}")

怎么判断一个请求该用 GET 还是 POST?

打开浏览器 F12 的 Network Tab,刷新页面或者操作一下,看对应请求的 Method 列:

  • 显示 GET → 用 requests.get()
  • 显示 POST → 用 requests.post()

别猜,看浏览器怎么发的,你就怎么发。
在这里插入图片描述


五、实战练手:抓取一个公开榜单

来做一个稍微完整的例子:抓取新浪新闻首页的热点新闻标题和链接。
新浪新闻(https://news.sina.com.cn/)是国内最大的新闻门户网站之一,首页会展示最新的热点新闻。

分析页面结构

打开新浪新闻首页,F12 看 Elements
热点新闻的结构大致是:

<a href="https://news.sina.com.cn/xxx" class="linkNewsTopBold">新闻标题</a>

标题在 class="linkNewsTopBold"<a> 标签里。

写代码

"""
Day 02 练手:抓取新浪新闻首页热点新闻标题和链接
作者:梅雅达编程笔记
"""
import requests
from bs4 import BeautifulSoup

url = "https://news.sina.com.cn/"

# 设置请求头,伪装成浏览器
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

try:
    response = requests.get(url, headers=headers, timeout=10)
    response.encoding = response.apparent_encoding  # 自动检测编码
except requests.exceptions.Timeout:
    print(f"请求超时:{url}")
    exit()
except requests.exceptions.ConnectionError:
    print(f"连接失败:{url}(请检查网络)")
    exit()
except Exception as e:
    print(f"请求异常:{e}")
    exit()

if response.status_code != 200:
    print(f"请求失败,状态码:{response.status_code}")
    exit()

soup = BeautifulSoup(response.text, "lxml")

# 找到所有热点新闻链接
news_links = soup.find_all("a", class_="linkNewsTopBold")

# 过滤空标题和重复链接
filtered_news = []
seen_hrefs = set()

for link in news_links:
    title = link.get_text(strip=True)
    href = link.get("href")
    
    # 跳过空标题或无效链接
    if not title or len(title) < 5 or not href:
        continue
    
    # 跳过重复链接
    if href in seen_hrefs:
        continue
    
    seen_hrefs.add(href)
    filtered_news.append({"title": title, "href": href})

print(f"首页共 {len(filtered_news)} 条热点新闻:")
print()

for i, news in enumerate(filtered_news[:15], 1):
    print(f"{i:2d}. {news['title']}")
    print(f"    链接:{news['href']}")
    print()

在这里插入图片描述

运行之后,你会看到热点新闻的标题和链接整齐地打印出来。

这就是爬虫的基础流程:分析页面结构 → 找到数据位置 → 用代码提取→ 数据清洗


六、注意事项

1. 编码问题

有时候抓回来的内容是乱码,多半是编码不对。

大多数现代网站用 UTF-8,但也有些老网站用 GBK。requests 默认按 response.encoding 解码,但有时候不准。

解决方法:

import requests

try:
    response = requests.get(url, timeout=10)
    response.encoding = response.apparent_encoding  # 自动检测编码
    html = response.text
except requests.exceptions.RequestException as e:
    print(f"请求失败:{e}")

2. 请求头

有些网站会检查你是不是浏览器。如果请求头太简单,可能会被拒绝。

最简单的伪装:

import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
try:
    response = requests.get(url, headers=headers, timeout=10)
except requests.exceptions.RequestException as e:
    print(f"请求失败:{e}")

这个 User-Agent 表示"我是 Chrome 浏览器"。

3. 请求频率

不要一秒发几十次请求,人家服务器扛不住。

import requests
import time

for url in urls:
    try:
        response = requests.get(url, timeout=10)
        print(f"请求 {url} 状态码:{response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"请求 {url} 失败:{e}")
    time.sleep(1)  # 每次请求间隔 1 秒

养成好习惯,别给人添麻烦。


📊 本篇成本透明栏

项目数值
API 调用次数0
消耗 Token0
成本¥0

本篇纯本地操作,不需要任何 API Key。


练手改造题

**改造 1(基础):修改新浪新闻的代码,把新闻标题和链接存到一个列表里,然后打印成 Markdown 格式([标题](链接))。。

改造 2(进阶): 用 F12 分析一个你喜欢的网站(比如 CSDN 首页、知乎热榜、新华网),看看文章/话题的标题在 HTML 里的位置,尝试用 BeautifulSoup 提取出来。提示:先用 Elements Tab 找到数据所在的标签和 class/id


下期预告

Day 03 · 列表页抓取:批量拿数据

今天抓了一个页面,明天批量抓。列表页的结构分析、CSS 选择器和 XPath 的高级用法、数据清洗(去空值、去重、格式化)。从抓一条,到抓一百条。


📚 资源与工具


梅雅达编程笔记,只教能落地的东西 🍃

往期回顾

Day 01 · 爬虫能干啥不能干啥

下一篇: Day 03 · 列表页抓取:批量拿数据

专栏订阅:Python 爬虫实战


©️ 梅雅达编程笔记原创 · 首发 CSDN · 转载请注明出处

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐