我将为你提供一个全面、从入门到实践的指南,涵盖从简单到复杂的多种方法,并重点讲解如何处理 WordPress 的动态加载内容。

目录
- 准备工作
- 安装必要的 Python 库
- 理解 WordPress 的基本结构
- 使用
requests+BeautifulSoup(静态页面采集)- 原理
- 代码示例
- 优缺点分析
- 使用
selenium(动态页面采集)- 原理
- 安装与配置
- 代码示例
- 优缺点分析
- 高级技巧与最佳实践
- 处理分页
- 设置请求头模拟浏览器
- 处理反爬机制
- 使用代理 IP
- 数据存储
- 一个完整的实战案例
- 目标:采集一个 WordPress 博客的所有文章标题、链接、摘要和发布日期。
- 代码实现 (使用
requests+BeautifulSoup)
- 重要提醒:法律与道德规范
准备工作
安装必要的 Python 库
你需要安装几个核心库来帮助你完成采集任务。
# 用于发送 HTTP 请求,获取网页内容 pip install requests # 用于解析 HTML 和 XML 文档,提取数据 pip install beautifulsoup4 # 可选,用于处理数据,特别是表格数据 pip install pandas # 可选,用于动态页面采集 pip install selenium # 可选,用于处理 JavaScript 渲染的页面(是 Selenium 的替代品,更现代) pip install playwright
理解 WordPress 的基本结构
大多数 WordPress 网站的文章列表页面都有共同的特征:
- 文章容器: 所有文章通常被包裹在一个具有特定 CSS 类的
<div>或<article>标签中,常见的类名有post,entry,hentry,type-post等。 - : 文章标题通常在
<h2>,<h3>或<h1>标签内,并且链接到文章详情页 (<a>标签)。 - 文章摘要: 文章的摘要或部分内容可能在
<p>标签内,或者位于一个特定的div.excerpt中。 - 发布日期: 发布日期通常在
<time>标签或一个带有date类的<span>标签中。 - 分页: 分页通常通过 "Older Posts" / "Newer Posts" 链接实现,或者使用 "Load More" 按钮以及 AJAX 无限滚动。
开发者工具是你的好朋友:在浏览器中按 F12 打开开发者工具,选择 "Elements" (元素) 面板,然后点击 "Select an element in the page to inspect it" (选择页面元素以检查) 按钮,点击你想要采集的内容(如一篇文章标题),这样你就能精确地看到它的 HTML 结构和 CSS 类名。
方法一:使用 requests + BeautifulSoup (静态页面)
这种方法适用于在服务器端就已经生成好,直接返回给浏览器的 WordPress 网站,这是最快、最轻量级的方法。

原理
requests库向目标 WordPress 网站的 URL 发送一个 HTTP GET 请求。- 服务器返回 HTML 页面的源代码。
BeautifulSoup将 HTML 源代码解析成一个对象,方便我们通过标签、类名等来定位和提取数据。
代码示例
假设我们要采集 https://wordpress.org/news/ 的文章标题和链接。
import requests
from bs4 import BeautifulSoup
import time
# 目标 URL
url = 'https://wordpress.org/news/'
# 设置请求头,模拟浏览器访问
# 有些网站会拒绝没有 User-Agent 的请求
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:
# 1. 发送请求
response = requests.get(url, headers=headers, timeout=10)
# 如果请求失败 (404, 500),抛出异常
response.raise_for_status()
# 2. 解析 HTML
soup = BeautifulSoup(response.text, 'html.parser')
# 3. 定位数据容器 (通过检查元素找到的类名)
# 在 wordpress.org/news 中,文章在 'post' 类的 div 中
posts = soup.find_all('div', class_='post')
if not posts:
print("没有找到文章容器,请检查 HTML 结构是否变化。")
else:
# 4. 遍历并提取数据
for post in posts:
# 提取标题 (在 h2 标签的 a 标签里)
title_tag = post.find('h2', class_='post-title')
if title_tag:
title = title_tag.get_text(strip=True)
link = title_tag.find('a')['href']
print(f"标题: {title}")
print(f"链接: {link}")
print("-" * 30)
# 礼貌性暂停,避免对服务器造成过大压力
time.sleep(1)
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
优缺点分析
- 优点:
- 速度快,资源消耗低。
- 代码简单,易于理解和实现。
- 缺点:
- 无法处理由 JavaScript 动态加载的内容(点击 "Load More" 按钮后出现的新文章)。
- 容易被简单的反爬机制识别。
方法二:使用 selenium (动态页面)
WordPress 网站使用了 AJAX、无限滚动或 "Load More" 按钮来动态加载文章,requests 就无能为力了,这时我们需要一个能控制浏览器、执行 JavaScript 的工具,selenium 是最经典的选择。
原理
selenium启动一个真实的浏览器(如 Chrome, Firefox)。- 通过代码控制这个浏览器打开目标网页。
- 等待页面上的 JavaScript 执行完毕,动态内容加载出来。
- 获取浏览器当前页面的完整 HTML 源代码。
- 将 HTML 源代码交给
BeautifulSoup进行解析和数据提取。
安装与配置
- 安装
selenium库 (pip install selenium)。 - 下载对应浏览器的 WebDriver,如果你使用 Chrome 浏览器,需要下载 ChromeDriver。
- ChromeDriver 下载地址: https://googlechromelabs.github.io/chrome-for-testing/
- 确保 WebDriver 的版本与你的 Chrome 浏览器版本大致匹配。
- 下载后,将
chromedriver.exe(Windows) 或chromedriver(Mac/Linux) 放在你的项目目录下,或者系统PATH路径中。
代码示例
假设我们要采集一个使用 "Load More" 按钮加载文章的 WordPress 网站。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
# --- 配置 Selenium ---
# ChromeDriver 的路径 (如果你把它放在了项目根目录下)
# CHROME_DRIVER_PATH = './chromedriver'
# 如果在系统PATH中,可以不指定路径
# 设置 Chrome 选项
chrome_options = Options()
# chrome_options.add_argument('--headless') # 无头模式,不显示浏览器窗口
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
# 初始化 WebDriver
# service = Service(executable_path=CHROME_DRIVER_PATH)
# driver = webdriver.Chrome(service=service, options=chrome_options)
# 如果chromedriver在PATH中,可以这样写
driver = webdriver.Chrome(options=chrome_options)
url = 'https://example.com/a-wordpress-site-with-load-more/' # 替换成你的目标网站
try:
# 1. 打开网页
driver.get(url)
# 2. 循环点击 "Load More" 按钮,直到没有更多内容
while True:
try:
# 尝试找到 "Load More" 按钮 (类名可能需要根据实际情况修改)
load_more_button = driver.find_element(By.CSS_SELECTOR, '.load-more-button-class')
print("找到 'Load More' 按钮,点击中...")
load_more_button.click()
# 等待新内容加载
time.sleep(2)
except:
# 如果找不到按钮,说明已经加载完毕
print("未找到 'Load More' 按钮,所有内容已加载完毕。")
break
# 3. 获取页面源代码
page_source = driver.page_source
# 4. 使用 BeautifulSoup 解析
soup = BeautifulSoup(page_source, 'html.parser')
# 5. 提取数据 (这里的解析逻辑和方法一相同)
posts = soup.find_all('article', class_='post') # 假设文章在 article.post 中
for post in posts:
title_tag = post.find('h2', class_='entry-title')
if title_tag:
title = title_tag.get_text(strip=True)
link = title_tag.find('a')['href']
print(f"标题: {title}")
print(f"链接: {link}")
print("-" * 30)
finally:
# 6. 关闭浏览器
driver.quit()
优缺点分析
- 优点:
- 功能强大,可以处理任何由 JavaScript 渲染的动态内容。
- 可以模拟用户交互(点击、输入、滚动等)。
- 缺点:
- 速度慢,资源消耗大(需要启动一个浏览器)。
- 配置相对复杂(需要下载和管理 WebDriver)。
- 代码更复杂。
高级技巧与最佳实践
处理分页
除了 "Load More",WordPress 还常用传统的分页链接。

- 静态分页: URL 形如
.../page/2/,.../page/3/,你可以构造这些 URL,然后用requests循环请求。for page_num in range(1, 6): # 采集前5页 url = f'https://example.com/blog/page/{page_num}/' # ... 发送请求和解析的代码 ...
设置请求头
如代码中所示,User-Agent 是最基本的请求头,可以让你看起来像一个正常的浏览器访问。Referer 也可以在某些情况下使用。
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',
'Accept-Language': 'en-US,en;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
}
处理反爬机制
- IP 封禁: 如果你请求太频繁,你的 IP 可能会被临时或永久封禁。
- 解决方案: 设置
time.sleep(random.uniform(1, 3))在每次请求之间随机暂停,使用代理 IP 池。
- 解决方案: 设置
- 验证码: 网站可能会弹出验证码。
- 解决方案:
selenium可以手动处理,但自动化处理验证码(尤其是 reCAPTCHA v2)非常困难,通常需要第三方服务。
- 解决方案:
数据存储
采集到的数据最终需要存储起来。
-
CSV 文件: 适合存储结构化的表格数据。
import csv with open('articles.csv', 'w', newline='', encoding='utf-8') as f: writer = csv.writer(f) writer.writerow(['标题', '链接', '#39;]) for post in posts: # ... 提取数据 ... writer.writerow([title, link, excerpt]) -
JSON 文件: 灵活性高,适合存储嵌套或非结构化数据。
import json data = [] for post in posts: # ... 提取数据 ... data.append({'title': title, 'link': link, 'excerpt': excerpt}) with open('articles.json', 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) -
数据库: 如果数据量巨大,需要频繁查询,应使用 MySQL, PostgreSQL 或 MongoDB 等数据库。
一个完整的实战案例
目标: 采集 https://quotes.toscrape.com/ (一个用来练习爬虫的网站,虽然不是WordPress,但结构类似) 的所有名言、作者和标签。
方法: 使用 requests + BeautifulSoup。
import requests
from bs4 import BeautifulSoup
import csv
import time
base_url = 'http://quotes.toscrape.com/'
all_quotes_data = []
# 循环处理所有分页
while True:
print(f"正在采集: {base_url}")
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:
response = requests.get(base_url, headers=headers, timeout=10)
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"请求失败: {e}")
break
soup = BeautifulSoup(response.text, 'html.parser')
# 1. 提取当前页面的名言
quotes = soup.find_all('div', class_='quote')
if not quotes:
print("未找到名言,采集结束。")
break
for quote in quotes:
text = quote.find('span', class_='text').get_text(strip=True)
author = quote.find('small', class_='author').get_text(strip=True)
tags = [tag.get_text(strip=True) for tag in quote.find_all('a', class_='tag')]
all_quotes_data.append({
'text': text,
'author': author,
'tags': ', '.join(tags)
})
print(f"已采集: {text[:30]}... by {author}")
# 2. 寻找下一页链接
next_button = soup.find('li', class_='next')
if next_button:
next_page_url = next_button.find('a')['href']
# 构造完整的下一页 URL
base_url = base_url.rstrip('/') + next_page_url
else:
# 如果没有下一页按钮,退出循环
print("已到达最后一页。")
break
# 礼貌性暂停
time.sleep(1)
# 3. 将数据保存到 CSV 文件
if all_quotes_data:
with open('quotes.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=['text', 'author', 'tags'])
writer.writeheader()
writer.writerows(all_quotes_data)
print(f"\n采集完成!共采集 {len(all_quotes_data)} 条名言,已保存到 quotes.csv。")
else:
print("\n未能采集到任何数据。")
重要提醒:法律与道德规范
在开始任何爬虫项目之前,请务必牢记以下几点:
robots.txt协议: 几乎所有网站都有一个robots.txt文件(https://example.com/robots.txt),它规定了哪些页面允许爬虫访问,哪些不允许。请务必遵守这个协议,使用robotparser模块可以检查你的爬虫是否被允许访问某个 URL。- 服务条款: 仔细阅读目标网站的服务条款,很多网站明确禁止自动化采集。
- 频率限制: 不要对服务器造成过大压力,设置合理的请求间隔(
time.sleep(1)),避免在短时间内发送大量请求。 - 数据所有权: 明确你采集的数据的版权和使用范围,不要将采集到的数据用于非法或商业用途,除非你获得了所有者的许可。
- 尊重隐私: 如果采集的数据涉及个人信息,请务必遵守相关隐私保护法律(如 GDPR, CCPA)。
从 requests 开始,如果遇到动态内容再升级到 selenium 或 playwright,始终将道德和合法性放在第一位,祝你采集顺利!
