核心概念:静态页面 vs. 动态页面
在开始之前,首先要明白你要抓取的是哪种类型的页面。

-
静态页面:
- 特点在服务器上已经完全生成好,直接以 HTML 文件的形式发送给浏览器,内容是固定的,不会根据用户行为而改变。
- 例子:一个公司的“关于我们”页面、一篇博客文章、一个产品介绍页。
- 抓取方式:相对简单,直接获取 HTML 源代码,然后从中解析出你需要的信息即可。
-
动态页面:
- 特点:初始的 HTML 文件通常只包含一个框架和加载脚本,页面内容是通过 JavaScript 在浏览器端动态从服务器 API 获取并渲染的。
- 例子:大多数现代网站,如社交媒体动态、商品搜索结果、实时数据看板。
- 抓取方式:更复杂,需要模拟浏览器的行为,先执行 JavaScript,等待内容加载完成后再获取渲染后的 HTML。
本指南主要针对静态页面,但也会在最后提到如何处理动态页面的基本思路。
抓取工具与语言选择
你可以选择多种工具来实现抓取,从简单的命令行工具到强大的编程语言库。

命令行工具 (适合快速、简单的任务)
-
curl:一个强大的命令行工具,用于传输数据,你可以用它直接下载网页的 HTML 源代码。# 基本用法,将网页内容保存到文件 curl -o page.html https://www.example.com # 直接在终端输出网页源码 curl https://www.example.com
-
wget:另一个非常流行的命令行下载工具,功能比curl更侧重于下载。# 递归下载整个网站(注意:这可能会对服务器造成巨大压力,请谨慎使用!) wget --mirror --convert-links --adjust-extension --page-requisites --no-parent http://example.com # 下载单个页面 wget -O page.html https://www.example.com
优点:无需编程,快速直接。 缺点:功能有限,难以处理复杂的解析逻辑。
编程语言 (最灵活、最强大的方式)
这是最主流和推荐的方式,尤其当你需要处理大量数据或复杂的抓取逻辑时。

-
Python (首选推荐):拥有最成熟、最丰富的爬虫生态系统。
Requests:用于发送 HTTP 请求,获取网页内容,它简单易用,是 Python 爬虫的“标准”。Beautiful Soup:用于解析 HTML 和 XML 文档,它能将复杂的 HTML 代码解析成一个 Python 对象,让你可以方便地通过标签、属性、CSS 选择器等来查找和提取数据。Scrapy:一个功能强大的爬虫框架,当你需要构建大规模、可维护的爬虫项目时,Scrapy 是不二之选,它包含了请求调度、数据提取、错误处理、数据存储等全套功能。
-
Node.js:如果你是前端开发者,用 Node.js 会非常顺手。
axios或node-fetch:相当于 Python 的Requests,用于发送 HTTP 请求。Cheerio:相当于 Python 的Beautiful Soup,它提供了类似 jQuery 的 API 来解析和操作服务器端的 HTML,速度非常快。
-
其他语言:
- Java:
Jsoup(解析HTML) +HttpClient(发送请求)。 - Go:
net/http(标准库) +goquery(类似jQuery的解析器)。
- Java:
Python 抓取静态页面实战 (以 Requests + Beautiful Soup 为例)
这是最经典、最适合新手的组合,我们将一步步完成一个完整的抓取任务。
任务目标:抓取维基百科 "Python (programming language)" 页面,提取其简介段落和所有信息表格。
第1步:环境准备
确保你已经安装了 Python,然后安装必要的库:
pip install requests pip install beautifulsoup4 pip install lxml # 一个高效的HTML解析器,推荐使用
第2步:发送请求,获取网页内容
使用 requests.get() 方法向目标 URL 发送 GET 请求,并获取响应对象。
import requests
# 目标URL
url = 'https://en.wikipedia.org/wiki/Python_(programming_language)'
# 设置请求头,模拟浏览器访问,避免被一些简单的反爬机制拦截
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
try:
# 发送GET请求
response = requests.get(url, headers=headers)
# 检查请求是否成功 (状态码 200 表示成功)
response.raise_for_status()
# 获取网页的HTML内容 (response.text)
html_content = response.text
print("成功获取网页内容!")
# print(html_content[:500]) # 打印前500个字符,预览一下
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
第3步:解析 HTML,提取数据
现在我们有了 HTML 内容,使用 Beautiful Soup 来解析它并提取我们需要的信息。
from bs4 import BeautifulSoup
# 假设我们已经从上一步获得了 html_content
# soup = BeautifulSoup(html_content, 'lxml')
# 为了演示,我们直接使用上一步的代码
url = 'https://en.wikipedia.org/wiki/Python_(programming_language)'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
response = requests.get(url, headers=headers)
html_content = response.text
# 创建Beautiful Soup对象
soup = BeautifulSoup(html_content, 'lxml')
# 1. 提取简介段落
# 使用CSS选择器找到第一个class为"infobox"的元素之前的所有<p>标签
intro_paragraphs = soup.select('.infobox ~ p')
print("\n--- 网页简介 ---")
for p in intro_paragraphs[:2]: # 通常前两个就是简介
print(p.get_text(strip=True)) # get_text()获取文本内容,strip()去除首尾空白
# 2. 提取信息表格
# 找到所有class为"infobox"的表格
infoboxes = soup.find_all('table', class_='infobox')
print("\n--- 信息表格 ---")
if infoboxes:
# 通常第一个就是主信息表
first_infobox = infoboxes[0]
# 遍历表格中的每一行<tr>
for row in first_infobox.find_all('tr'):
# 找到表头<th>和数据<td>
header = row.find('th')
data = row.find('td')
if header and data:
print(f"{header.get_text(strip=True)}: {data.get_text(strip=True)}")
常用 Beautiful Soup 选择器:
soup.find('tag'): 找到第一个匹配的标签。soup.find_all('tag'): 找到所有匹配的标签。soup.select('CSS选择器'): 使用 CSS 选择器语法查找元素,非常强大和灵活。'#id': 通过ID查找。'.class': 通过类名查找。'tag': 通过标签名查找。'tag[attr="value"]': 通过属性查找。
.get_text(): 获取元素的纯文本内容。[attr]: 获取元素的属性值,img['src']获取图片链接。
第4步:数据存储
提取出的数据通常是字典或列表的形式,你可以将其保存为文件。
保存为 CSV 文件:
import csv
# 假设我们提取了一个信息列表
data_to_save = [
{"key": "Paradigm", "value": "Multi-paradigm"},
{"key": "Designed by", "value": "Guido van Rossum"},
{"key": "First appeared", "value": "1991"}
]
# 写入CSV文件
with open('python_info.csv', 'w', newline='', encoding='utf-8') as csvfile:
fieldnames = ['key', 'value']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(data_to_save)
print("\n数据已保存到 python_info.csv")
进阶与最佳实践
当你掌握了基本操作后,需要注意以下几点,让你的爬虫更健壮、更专业。
-
处理反爬机制
-
设置
User-Agent:如上所示,伪装成浏览器。 -
使用代理 IP:当你的请求过于频繁时,IP 可能会被封,使用代理池可以轮换 IP。
-
控制请求频率:在两次请求之间加入随机延时,避免对服务器造成过大压力。
import time import random time.sleep(random.uniform(1, 3)) # 随机等待1到3秒
-
处理验证码:简单的验证码可以借助第三方服务(如 2Captcha)解决。
-
-
数据清洗 从 HTML 中提取的文本通常包含多余的空格、换行符,使用
.get_text(strip=True)或正则表达式进行清理。 -
错误处理 网络请求是不可靠的,可能会因为各种原因失败(如网络中断、404 Not Found、500 Server Error),使用
try...except块来捕获异常,让你的程序更稳定。 -
遵守
robots.txt这是一个位于网站根目录下的文件(https://www.example.com/robots.txt),它告诉爬虫哪些页面可以抓取,哪些不可以,在抓取一个网站前,务必先查看并遵守其robots.txt协议。 -
处理分页 如果数据分布在多个页面,你需要分析分页的规律(通常是 URL 中的页码参数),然后构建循环来抓取所有页面。
如何应对动态页面?
如果发现直接抓取到的 HTML 中没有你想要的数据,那它很可能是一个动态页面,这时你需要:
-
使用浏览器开发者工具:
- 打开目标网站,按
F12打开开发者工具。 - 切换到 Network (网络) 选项卡。
- 刷新页面,筛选出
XHR或Fetch类型的请求。 - 查看这些请求的 URL 和 Response,你会发现这些请求返回的通常是 JSON 格式的数据,这就是页面内容的来源。
- 打开目标网站,按
-
模拟 API 请求:
- 直接复制这个 API 请求的 URL 和 Headers(特别是
Authorization和X-Requested-With等关键头)。 - 使用
requests库直接向这个 API 发送请求,获取 JSON 数据,这比解析渲染后的 HTML 要简单、高效得多。
- 直接复制这个 API 请求的 URL 和 Headers(特别是
-
使用无头浏览器:
- 如果数据是通过非常复杂的 JavaScript 交互生成的,或者需要登录后才能获取,那么你需要使用 Selenium、Playwright 或 Pyppeteer 等工具。
- 这些工具可以自动化一个真实的浏览器(如 Chrome 或 Firefox),让它执行 JavaScript,加载页面,然后再从浏览器中获取最终的 HTML 源码。
- 缺点:速度慢,资源消耗大,是最后的手段。
| 步骤 | 工具/方法 | 说明 |
|---|---|---|
| 分析目标 | 浏览器开发者工具 | 检查是静态还是动态页面,找到数据在 HTML 中的位置或 API 接口。 |
| 发送请求 | requests (Python) / axios (Node.js) |
获取网页的原始 HTML 内容。 |
| 解析数据 | Beautiful Soup (Python) / Cheerio (Node.js) |
从 HTML 中精准地提取你需要的信息。 |
| 存储数据 | CSV, Excel, JSON, 数据库 | 将提取的结构化数据保存下来。 |
| 进阶优化 | 代理、延时、robots.txt |
让爬虫更健壮、更礼貌。 |
对于静态页面,遵循以上步骤,你就能高效地完成抓取任务,祝你学习顺利!
