BeautifulSoup 和 Selenium 都能处理网页,但定位完全不同。
选择原则
如果页面 HTML 已经包含目标数据,用 BeautifulSoup。它快、简单、资源消耗低。
如果页面需要执行 JavaScript、登录、点击、滚动或处理动态内容,用 Selenium。
BeautifulSoup 初始化
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, "html.parser")查找元素
first_p = soup.find("p")
all_links = soup.find_all("a")
title = soup.find("p", class_="title")CSS 选择器:
links = soup.select("a.sister")
id_link = soup.select("#link1")
nested = soup.select("p.story a")获取文本和属性:
text = soup.find("p").get_text()
href = soup.find("a").get("href")修改和删除:
tag = soup.find("b")
tag.string = "New Title"
link = soup.find("a", id="link1")
link.decompose()Selenium 初始化
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://example.com")常用浏览器操作:
driver.maximize_window()
driver.refresh()
driver.back()
driver.forward()
print(driver.current_url)
print(driver.title)元素定位
from selenium.webdriver.common.by import By
driver.find_element(By.ID, "username")
driver.find_element(By.NAME, "email")
driver.find_element(By.CSS_SELECTOR, "button.submit")
driver.find_element(By.XPATH, "//div[@id='content']")操作元素
input_box.send_keys("my_username")
input_box.clear()
button.click()
form.submit()显式等待
动态页面必须等待条件,而不是盲目 sleep。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located((By.ID, "username"))
)复杂页面操作
滚动:
driver.execute_script("arguments[0].scrollIntoView();", element)弹窗:
alert = driver.switch_to.alert
alert.accept()iframe:
driver.switch_to.frame("iframe_name")
driver.switch_to.default_content()截图:
driver.save_screenshot("page.png")
element.screenshot("element.png")实践顺序通常是:静态 HTML 解析优先,其次解析页面内 JSON,最后才启动浏览器自动化。
延伸理解
复习这篇时,不要只记住名词,要把重点放在 静态 HTML 解析、Selenium 动态页面、等待策略、元素定位和反脆弱爬虫流程。这类知识如果只停留在定义层面,很容易在面试或项目中答得很散。更好的理解方式是把它放进一个具体场景:谁在调用它,输入从哪里来,失败后谁负责恢复,数据或状态会不会被重复处理。
- 爬虫工程的难点通常不是发请求,而是页面变化、等待策略、去重、限速、异常恢复和数据质量。
- 选择 BeautifulSoup、Selenium 或 Scrapy 时,要先判断页面是否动态、数据规模和后续清洗需求。
- 可靠爬虫需要日志、断点续跑、失败重试和字段级校验,不能只依赖一次成功运行。
在真实项目中,可以把它当成一个判断框架:先确认输入、约束、失败场景和可观测性,再决定具体工具或写法。 如果一个方案看起来很简单,要继续追问它在规模扩大、权限变化、异常恢复和团队协作下是否仍然成立。
实践检查清单
- 明确这个知识点在系统中的位置:是开发时约束、运行时能力、基础设施能力,还是协作流程。
- 写出一个最小可运行例子,并补一个失败例子;只会写 happy path 说明理解还不够稳。
- 记录常见误用:例如边界条件、权限假设、性能假设、同步/异步差异或环境差异。
- 把概念和项目经历关联起来:如果面试被追问,可以用自己的项目说明为什么这样选。
- 最后用一句话总结取舍:它牺牲了什么,换来了什么。
自测问题
- 这个主题解决的核心问题是什么?
- 如果不用当前方案,还有哪些替代方案?代价是什么?
- 最容易出错的边界条件在哪里?
- 如何在代码、测试或监控中验证它真的可靠?
项目化应用场景
可以把这类知识放到一个招聘信息或商品信息采集系统里理解:先判断页面是静态 HTML 还是动态渲染,再选择 BeautifulSoup、Selenium 或 Scrapy;采集后要做字段清洗、去重、失败重试和持久化。稳定爬虫的关键不是一次能抓到数据,而是页面结构变化、网络超时、反爬限制和部分字段缺失时仍然能恢复。
常见误区:
- 直接写死脆弱 selector,没有 fallback。
- 没有限速和重试,容易被封或丢数据。
- 只保存原始数据,不做字段级质量检查。