
- 使用 Selenium:控制浏览器(如 Chrome, Firefox)打开网页,与页面元素进行交互(点击、输入、滚动等)。
- 抓取数据:从网页的 HTML 结构中提取你感兴趣的信息(如商品标题、价格、新闻标题、文章内容等)。
- 处理数据:对抓取到的数据进行清洗、格式化,使其符合数据库的存储要求。
- 连接数据库:使用 Python 的数据库连接库(如
pymysql用于 MySQL,psycopg2用于 PostgreSQL,sqlite3用于 SQLite)建立与数据库的连接。 - 存储数据:将处理好的数据通过 SQL 语句(如
INSERT)插入到数据库的相应表中。
第一步:环境准备
在开始之前,请确保你已经安装了必要的库。
-
Selenium:
pip install selenium
-
浏览器驱动:
- 你需要下载与你浏览器版本匹配的 WebDriver,如果你使用 Chrome 浏览器,你需要下载 ChromeDriver。
- 重要:确保 WebDriver 的版本与你的 Chrome 浏览器版本大致匹配。
- 将下载好的
chromedriver.exe(Windows) 或chromedriver(macOS/Linux) 放在你的项目目录下,或者将其路径添加到系统的环境变量PATH中。
-
数据库连接库:
(图片来源网络,侵删)- MySQL:
pip install pymysql - PostgreSQL:
pip install psycopg2-binary - SQLite: Python 内置,无需额外安装。
- MySQL:
第二步:一个完整的示例(抓取书籍信息并存入 SQLite)
我们将抓取一个假设的图书列表网站,并将书名和价格存入 SQLite 数据库。
目标网站分析
假设我们有一个简单的 HTML 页面,结构如下:
<!DOCTYPE html>
<html>
<head>图书列表</title>
</head>
<body>
<h1>我的书架</h1>
<div class="book-list">
<div class="book-item">
<h2 class="title">Python编程:从入门到实践</h2>
<p class="price">¥89.00</p>
</div>
<div class="book-item">
<h2 class="title">流畅的Python</h2>
<p class="price">¥129.00</p>
</div>
<div class="book-item">
<h2 class="title"> Selenium自动化测试:基于Python</h2>
<p class="price">¥79.00</p>
</div>
</div>
</body>
</html>
Python 代码实现
import time
import sqlite3
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
# --- 1. Selenium 设置 ---
# 设置 Chrome 选项 (例如无头模式)
chrome_options = Options()
# chrome_options.add_argument("--headless") # 无头模式,不显示浏览器窗口
chrome_options.add_argument("--disable-gpu")
# 指定 ChromeDriver 路径 (如果不在 PATH 中)
# service = Service(executable_path='path/to/your/chromedriver')
# driver = webdriver.Chrome(service=service, options=chrome_options)
# chromedriver 在 PATH 中,可以直接这样初始化
driver = webdriver.Chrome(options=chrome_options)
# --- 2. 数据库设置 ---
# 创建一个内存中的 SQLite 数据库 (如果需要持久化,将 ':memory:' 替换为文件名,如 'books.db')
conn = sqlite3.connect(':memory:')
cursor = conn.cursor()
# 创建一个表来存储书籍信息
create_table_query = """
CREATE TABLE IF NOT EXISTS books (
id INTEGER PRIMARY KEY AUTOINCREMENT,TEXT NOT NULL,
price TEXT NOT NULL
)
"""
cursor.execute(create_table_query)
print("数据库表 'books' 创建成功。")
# --- 3. 抓取数据 ---
try:
# 打开目标网页 (这里我们用一个本地HTML文件作为示例)
# 在实际应用中,这里应该是真实的URL,如 driver.get("https://www.example.com/books")
driver.get("file:///path/to/your/local_books.html") # !!! 请替换为你的本地HTML文件路径
# 等待页面加载
time.sleep(2)
# 定位所有的书籍元素
book_elements = driver.find_elements(By.CLASS_NAME, "book-item")
print(f"找到 {len(book_elements)} 本书。")
# 遍历每个书籍元素
for book in book_elements:
# 提取书名和价格
title_element = book.find_element(By.CLASS_NAME, "title")
price_element = book.find_element(By.CLASS_NAME, "price")
title = title_element.text
price = price_element.text
print(f"抓取到: 书名='{title}', 价格='{price}'")
# --- 4. 将数据存入数据库 ---
# 使用参数化查询来防止 SQL 注入
insert_query = "INSERT INTO books (title, price) VALUES (?, ?)"
cursor.execute(insert_query, (title, price))
# 提交事务
conn.commit()
print(f"成功将 {cursor.rowcount} 条数据插入数据库。")
# --- 5. 验证数据 ---
print("\n--- 数据库中的内容 ---")
cursor.execute("SELECT * FROM books")
rows = cursor.fetchall()
for row in rows:
print(row)
except Exception as e:
print(f"发生错误: {e}")
# 如果出错,回滚事务
conn.rollback()
finally:
# --- 6. 关闭连接 ---
# 关闭浏览器
driver.quit()
# 关闭数据库连接
conn.close()
print("浏览器和数据库连接已关闭。")
关键点详解
Selenium 部分
webdriver.Chrome(): 初始化一个 Chrome 浏览器实例。driver.get(url): 导航到指定的 URL。- 定位元素:
find_elements(): 返回一个元素列表,用于获取多个匹配项(如所有书籍)。find_element(): 返回单个元素。By.CLASS_NAME,By.ID,By.XPATH,By.CSS_SELECTOR等是常用的定位策略,XPath 和 CSS Selector 通常更强大和灵活。
element.text: 获取元素的可见文本内容。
数据库部分 (以 SQLite 为例)
sqlite3.connect(): 建立与数据库文件的连接。':memory:'表示创建一个临时的内存数据库,程序关闭后数据即丢失。conn.cursor(): 创建一个游标对象,所有 SQL 操作都通过这个游标执行。CREATE TABLE IF NOT EXISTS: 这是一个好习惯,可以防止脚本因表已存在而报错。cursor.execute(sql, params): 执行 SQL 语句。- 参数化查询:
VALUES (?, ?)是参数占位符。(title, price)是一个元组,包含了要替换占位符的实际值。这至关重要! 它可以防止 SQL 注入攻击,并使代码更清晰。
- 参数化查询:
conn.commit(): 将事务中的所有更改保存到数据库,在INSERT,UPDATE,DELETE操作后必须调用。conn.rollback(): 如果在事务中发生错误,调用此方法可以撤销所有未提交的更改。conn.close(): 关闭数据库连接,释放资源。
进阶:处理分页网站
对于有分页的网站,你需要模拟点击“下一页”按钮,并重复抓取和存储的过程。
# ... (前面的数据库和Selenium设置代码相同)
next_button_exists = True
page_num = 1
while next_button_exists:
print(f"--- 正在抓取第 {page_num} 页 ---")
# 1. 抓取当前页数据
# ... (你的抓取逻辑) ...
# 2. 存储到数据库
# ... (你的存储逻辑) ...
# 3. 尝试点击“下一页”按钮
try:
# 根据实际情况定位“下一页”按钮
next_button = driver.find_element(By.XPATH, "//a[contains(text(), '下一页')]")
next_button.click()
time.sleep(3) # 等待新页面加载
page_num += 1
except:
print("找不到“下一页”按钮,或已是最后一页。")
next_button_exists = False
# ... (后面的提交和关闭代码) ...
进阶:处理动态加载内容
很多现代网站使用 AJAX 或 JavaScript 动态加载数据,直接 find_element() 可能会失败,因为元素还不存在。

解决方案:显式等待
显式等待会告诉 Selenium 在执行下一步之前,等待某个条件(如元素可见、可点击)成立,或者超时。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# ...
try:
# 等待最多10秒,直到ID为"dynamic-content"的元素变得可见
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "dynamic-content"))
)
# 元素可见后,再进行操作
print(element.text)
except TimeoutException:
print("在指定时间内未找到元素。")
# ...
将 Selenium、Python 和数据库结合使用,可以实现强大的数据抓取和自动化测试流程,核心在于:
- Selenium 负责“看”和“动”:与浏览器交互,获取网页内容。
- Python 负责“想”和“做”:逻辑控制、数据清洗、与数据库通信。
- 数据库 负责“记”:持久化存储抓取到的结构化数据。
记住始终使用参数化查询来操作数据库,这是保证安全性的基本要求,合理使用显式等待来处理动态加载的网页,可以使你的脚本更加健壮。
