爬虫实战:BeautifulSoup/Scrapy/Selenium
本教程共 70 篇 · 第 66 篇 · 更新于 2026-07-22 · 约 6 分钟阅读
66. 爬虫实战:BeautifulSoup/Scrapy/Selenium
本节目标:掌握三种不同层次的爬虫技术,能根据场景选择合适工具,写出稳定的网页数据抓取程序。
爬虫的本质是「用程序代替浏览器,自动访问网页并提取数据」。简单的页面用请求库加解析器就能搞定;复杂的动态页面需要模拟浏览器行为;大规模抓取则需要框架来管理调度、去重和存储。
轻量级方案:requests + BeautifulSoup
对于静态 HTML 页面,先用 requests 获取源码,再用 BeautifulSoup 解析提取。
安装:
pip install requests beautifulsoup4
抓取示例:
import requests
from bs4 import BeautifulSoup
url = 'https://quotes.toscrape.com/'
resp = requests.get(url, timeout=10)
resp.encoding = 'utf-8'
soup = BeautifulSoup(resp.text, 'html.parser')
for quote in soup.find_all('div', class_='quote'):
text = quote.find('span', class_='text').get_text()
author = quote.find('small', class_='author').get_text()
tags = [t.get_text() for t in quote.find_all('a', class_='tag')]
print(f"{author}: {text[:30]}... 标签: {', '.join(tags)}")
BeautifulSoup 的常用查找方法:
find(tag, attrs):返回第一个匹配的标签。find_all(tag, attrs):返回所有匹配的标签列表。select(css_selector):用 CSS 选择器定位,比如soup.select('.quote .author')。.get_text():提取标签内的纯文本,自动去掉 HTML 标签。
Tip解析器推荐用
html.parser(Python 内置),或者装lxml获得更快的解析速度:BeautifulSoup(resp.text, 'lxml')。
处理分页:
for page in range(1, 6):
resp = requests.get(f'{url}/page/{page}')
soup = BeautifulSoup(resp.text, 'html.parser')
# ... 提取数据
Warning爬取前先看网站的
robots.txt(如https://example.com/robots.txt),遵守爬虫协议。控制请求频率,加time.sleep(1)避免封 IP。
工业级方案:Scrapy
Scrapy 是 Python 最强大的爬虫框架,自带异步调度、自动去重、数据管道、中间件扩展。适合中大型、需要持续运行的爬虫项目。
安装:
pip install scrapy
创建项目:
scrapy startproject myspider
cd myspider
scrapy genspider quotes quotes.toscrape.com
生成的爬虫文件 myspider/spiders/quotes.py:
import scrapy
class QuotesSpider(scrapy.Spider):
name = 'quotes'
allowed_domains = ['quotes.toscrape.com']
start_urls = ['https://quotes.toscrape.com/']
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').get(),
'author': quote.css('small.author::text').get(),
'tags': quote.css('div.tags a.tag::text').getall(),
}
next_page = response.css('li.next a::attr(href)').get()
if next_page:
yield response.follow(next_page, callback=self.parse)
Scrapy 的 response.css() 用 CSS 选择器提取数据,::text 取文本内容,::attr(href) 取属性值。yield 生成数据项,response.follow() 自动拼接 URL 并发送新请求。
运行爬虫并导出 JSON:
scrapy crawl quotes -o quotes.json
NoteScrapy 底层基于
twisted异步框架,天生支持高并发。单进程就能同时处理大量请求,不需要手动开线程。
动态页面方案:Selenium
越来越多的网站用 JavaScript 动态加载内容,requests 拿到的 HTML 里根本没有目标数据。这时候需要请出 Selenium,它驱动真实的浏览器(Chrome、Firefox),等页面完全渲染后再提取数据。
安装:
pip install selenium
并下载对应浏览器的 WebDriver,比如 ChromeDriver,确保版本和浏览器一致。
基础用法:
from selenium import webdriver
from selenium.webdriver.common.by import By
options = webdriver.ChromeOptions()
options.add_argument('--headless') # 无头模式,不弹出窗口
driver = webdriver.Chrome(options=options)
driver.get('https://quotes.toscrape.com/js/')
quotes = driver.find_elements(By.CSS_SELECTOR, 'div.quote')
for q in quotes:
text = q.find_element(By.CSS_SELECTOR, 'span.text').text
author = q.find_element(By.CSS_SELECTOR, 'small.author').text
print(f"{author}: {text[:30]}...")
driver.quit()
Selenium 的查找方式:
By.IDBy.CLASS_NAMEBy.CSS_SELECTORBy.XPATH
等待元素加载:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'div.quote')))
Tip无头模式(
--headless)在服务器上跑爬虫时很有用,不依赖图形界面。调试时去掉这个参数,方便观察浏览器行为。
三种方案怎么选
| 工具 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| requests + BeautifulSoup | 静态页面、小规模抓取 | 简单、快速、资源占用低 | 无法执行 JavaScript |
| Scrapy | 大规模、结构化抓取 | 异步高效、功能完整、可扩展 | 学习曲线较陡 |
| Selenium | 动态渲染页面、需要交互 | 真实浏览器,兼容性最好 | 慢、资源占用高 |
实际项目中经常组合使用:用 Selenium 拿到动态页面的源码,再交给 BeautifulSoup 解析;或者用 Scrapy 处理大部分静态页面,遇到动态页面再调用 Splash 或 Playwright。
小结
- requests + BeautifulSoup 是入门首选,适合简单的静态页面抓取。
- Scrapy 是工业级框架,适合需要调度、去重、持久化的大型项目。
- Selenium 驱动真实浏览器,是动态页面和复杂交互的最后手段。
- 爬虫有法律边界,遵守 robots.txt,尊重网站的反爬策略。
来源:参考了 runoob「Python 爬虫/Selenium 库/Scrapy 库」、w3cschool「Python3 爬虫实战教程」等,改写后所得。