Python爬虫实战⑧|Selenium模拟浏览器,JS渲染页面一把抓
·
author: 专注Python实战,分享爬虫与数据分析干货
title: Python爬虫实战⑧|Selenium模拟浏览器,JS渲染页面一把抓
update: 2026-04-26
tags: Python,爬虫,Selenium,浏览器自动化,JS渲染,动态页面,WebDriver
作者:专注Python实战,分享爬虫与数据分析干货
更新时间:2026年4月
适合人群:遇到JS渲染页面无法抓取、需要模拟浏览器操作的爬虫开发者
前言:有些页面,requests永远抓不到
有些网站,无论你怎么找API接口,数据就是拿不到——
- 网站用JS动态渲染,HTML源码是空的
- 需要先点击按钮、滚动页面才加载内容
- 有复杂的登录验证码
- 数据藏在iframe里
Selenium = 真实浏览器自动化。 它打开一个真实浏览器,像人一样操作,JS渲染的内容全部能拿到。
一、Selenium安装与配置
1.1 安装Selenium
pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple
Selenium 4.6+ 自带驱动管理器,无需手动下载驱动。但Chrome浏览器需要安装好。
1.2 第一个Selenium程序
from selenium import webdriver
# 打开Chrome浏览器
driver = webdriver.Chrome()
# 访问网页
driver.get("https://www.baidu.com")
# 获取页面标题
print("页面标题:", driver.title)
# 关闭浏览器
driver.quit()
1.3 常用配置选项
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
# 无头模式(不显示浏览器窗口,速度快,省资源)
options.add_argument("--headless")
# 禁用图片加载(加速)
options.add_argument("--disable-images")
# 设置窗口大小
options.add_argument("--window-size=1920,1080")
# 禁用GPU加速(避免无头模式下的报错)
options.add_argument("--disable-gpu")
# 禁用图片/CSS/JS(进一步加速)
prefs = {
"profile.managed_default_content_settings.images": 2,
"profile.managed_default_content_settings.stylesheets": 2,
}
options.add_experimental_option("prefs", prefs)
# 启动带配置的浏览器
driver = webdriver.Chrome(options=options)
driver.get("https://example.com")
driver.quit()
二、元素定位(8种方式)
Selenium用不同方式定位页面元素:
2.1 八种定位方法
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 1. ID定位(最快,推荐)
driver.find_element(By.ID, "kw")
# 2. Name定位
driver.find_element(By.NAME, "wd")
# 3. Class Name定位
driver.find_element(By.CLASS_NAME, "s_ipt")
# 4. Tag Name定位
driver.find_element(By.TAG_NAME, "input")
# 5. XPath定位(最强大)
driver.find_element(By.XPATH, "//input[@id='kw']")
# 6. CSS Selector定位
driver.find_element(By.CSS_SELECTOR, "#kw")
# 7. Link Text定位(链接文本)
driver.find_element(By.LINK_TEXT, "新闻")
# 8. Partial Link Text定位
driver.find_element(By.PARTIAL_LINK_TEXT, "新")
# 找多个元素(返回列表)
inputs = driver.find_elements(By.TAG_NAME, "input")
print(f"共找到 {len(inputs)} 个input标签")
2.2 XPath定位实战
# 文本包含
driver.find_element(By.XPATH, "//a[contains(text(),'登录')]")
# 属性匹配
driver.find_element(By.XPATH, "//button[@type='submit']")
# 组合条件
driver.find_element(By.XPATH, "//div[@class='card' and @id='main']")
# 按层级定位
driver.find_element(By.XPATH, "//form[@id='login']//button[@type='submit']")
# 模糊class
driver.find_element(By.XPATH, "//div[contains(@class, 'product')]")
三、元素操作
3.1 输入文本与点击
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 找到搜索框
search_box = driver.find_element(By.ID, "kw")
# 输入文本
search_box.send_keys("Python爬虫")
# 清空并重新输入
search_box.clear()
search_box.send_keys("Selenium教程")
# 按回车键
search_box.send_keys(Keys.RETURN)
# 找到搜索按钮并点击
search_btn = driver.find_element(By.ID, "su")
search_btn.click()
# 等待页面加载
import time
time.sleep(2)
# 获取当前URL
print("当前URL:", driver.current_url)
driver.quit()
3.2 下拉框处理
from selenium.webdriver.support.ui import Select
# 定位下拉框
select = Select(driver.find_element(By.TAG_NAME, "select"))
# 选择选项(三种方式)
select.select_by_value("option_value") # 按value属性
select.select_by_index(2) # 按索引(从0开始)
select.select_by_visible_text("显示文本") # 按显示文字
# 获取所有选项
for option in select.options:
print(option.text)
3.3 复选框和单选框
# 勾选复选框
checkbox = driver.find_element(By.ID, "agree")
if not checkbox.is_selected():
checkbox.click()
# 检查是否选中
print("是否选中:", checkbox.is_selected())
# 勾选单选框
radio = driver.find_element(By.XPATH, "//input[@name='gender' and @value='female']")
radio.click()
四、等待机制(最重要)
Selenium最大的坑:页面还没加载完就去找元素,找不到就报错。 解决方案是等待。
4.1 强制等待(简单但低效)
import time
time.sleep(3) # 强制等3秒
4.2 显式等待(推荐)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 等待某个元素出现(最多等10秒,每0.5秒检查一次)
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "kw"))
)
print("元素出现了:", element)
# 等待元素可点击
btn = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.ID, "su"))
)
btn.click()
# 等待URL包含特定字符
WebDriverWait(driver, 10).until(
EC.url_contains("baidu.com")
)
# 等待元素文本包含特定内容
WebDriverWait(driver, 10).until(
EC.text_to_be_present_in_element((By.ID, "result"), "Python")
)
4.3 常用等待条件
# 元素出现在DOM中
EC.presence_of_element_located((By.ID, "element_id"))
# 元素可见(能看见且有大小)
EC.visibility_of_element_located((By.ID, "element_id"))
# 元素可点击
EC.element_to_be_clickable((By.ID, "element_id"))
# 元素文本包含特定内容
EC.text_to_be_present_in_element((By.ID, "element_id"), "文本内容")
# URL包含特定字符
EC.url_contains("keyword")
# 页面标题包含特定字符
EC.title_contains("标题")
# alert出现
EC.alert_is_present()
# 等待多个元素
elements = WebDriverWait(driver, 10).until(
EC.presence_of_all_elements_located((By.CLASS_NAME, "item"))
)
五、执行JavaScript
Selenium可以执行任意JS代码:
# 滚动到页面底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# 滚动到指定元素位置
element = driver.find_element(By.ID, "comments")
driver.execute_script("arguments[0].scrollIntoView();", element)
# 获取页面高度
height = driver.execute_script("return document.body.scrollHeight;")
print("页面高度:", height)
# 点击隐藏的元素(用JS强制点击)
element = driver.find_element(By.XPATH, "//button[@id='hidden_btn']")
driver.execute_script("arguments[0].click();", element)
# 获取动态页面完整HTML(包含JS渲染后的内容)
html = driver.execute_script("return document.documentElement.outerHTML;")
print(html[:500])
# 设置输入框值(绕过readonly限制)
driver.execute_script("document.getElementById('date').value='2026-01-01';")
六、页面操作进阶
6.1 窗口和iframe切换
# 获取当前窗口句柄
current_window = driver.current_window_handle
print("当前窗口:", current_window)
# 打开新窗口
driver.execute_script("window.open('https://www.baidu.com');")
# 切换到新窗口
windows = driver.window_handles
driver.switch_to.window(windows[-1]) # 切换到最新窗口
print("新窗口:", driver.title)
# 切换回原窗口
driver.switch_to.window(current_window)
# 操作iframe
# 方法1:按ID或name切换
driver.switch_to.frame("iframe_id")
# 方法2:按索引切换
driver.switch_to.frame(0)
# 方法3:切回主文档
driver.switch_to.default_content()
# 操作alert/弹窗
alert = driver.switch_to.alert
print("弹窗文本:", alert.text)
alert.accept() # 点击确定
# alert.dismiss() # 点击取消
6.2 键盘和鼠标操作
from selenium.webdriver.common.action_chains import ActionChains
# 鼠标悬停
element = driver.find_element(By.ID, "dropdown")
ActionChains(driver).move_to_element(element).perform()
# 右键点击
ActionChains(driver).context_click(element).perform()
# 双击
ActionChains(driver).double_click(element).perform()
# 拖拽
source = driver.find_element(By.ID, "draggable")
target = driver.find_element(By.ID, "droppable")
ActionChains(driver).drag_and_drop(source, target).perform()
# 组合键
ActionChains(driver).key_down(Keys.CONTROL).send_keys("a").key_up(Keys.CONTROL).perform()
七、实战:Selenium版豆瓣Top250爬虫
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import csv
# 配置无头浏览器
options = Options()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome(options=options)
all_movies = []
try:
for page in range(2): # 演示2页
start = page * 25
url = f"https://movie.douban.com/top250?start={start}"
print(f"第{page+1}页: 加载中...", end=" ")
driver.get(url)
# 等待页面加载完成(至少看到电影列表)
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, "item"))
)
# 等待页面完全加载
time.sleep(1)
# 提取电影数据
items = driver.find_elements(By.CLASS_NAME, "item")
print(f"找到 {len(items)} 部电影")
for item in items:
try:
rank = item.find_element(By.CLASS_NAME, "pic").find_element(By.TAG_NAME, "em").text
title = item.find_element(By.CLASS_NAME, "title").text
rating = item.find_element(By.CLASS_NAME, "rating_num").text
try:
quote = item.find_element(By.CLASS_NAME, "inq").text
except:
quote = ""
all_movies.append([rank, title, rating, quote])
except Exception as e:
print(f" 解析出错: {e}")
# 礼貌延迟
time.sleep(2)
except Exception as e:
print(f"爬虫出错: {e}")
finally:
driver.quit()
# 保存数据
with open("豆瓣Top250_Selenium版.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.writer(f)
writer.writerow(["排名", "电影", "评分", "短评"])
writer.writerows(all_movies)
print(f"\n共 {len(all_movies)} 部电影,已保存")
for m in all_movies[:5]:
print(f" {m[0]:>3}. {m[1]:<15} {m[2]} {m[3]}")
八、知识卡
| 方法 | 说明 |
|---|---|
| webdriver.Chrome(options=) | 启动Chrome |
| driver.get(url) | 打开网页 |
| driver.quit() | 关闭浏览器 |
| By.ID / By.NAME / By.XPATH | 元素定位方式 |
| element.send_keys(text) | 输入文本 |
| element.click() | 点击元素 |
| WebDriverWait(driver, 10) | 显式等待(最安全) |
| EC.presence_of_element_located() | 等待元素出现 |
| EC.element_to_be_clickable() | 等待元素可点击 |
| driver.execute_script(js) | 执行JavaScript |
| driver.switch_to.frame() | 切换iframe |
| driver.switch_to.window() | 切换窗口 |
| ActionChains | 鼠标键盘操作链 |
| element.text | 获取元素文本 |
| element.get_attribute(“href”) | 获取元素属性 |
九、课后作业
必做题:
- 安装Selenium,编写第一个自动打开百度并搜索关键词的程序
- 用Selenium实现豆瓣Top250前2页的爬取
- 练习显式等待的3种条件
选做题:
- 用Selenium模拟登录任意网站
- 用execute_script实现无限滚动加载的页面抓取
完成作业的同学,把运行截图发到评论区!
Selenium = 爬虫的终极武器。 无论什么JS渲染、什么动态页面,只要浏览器能打开,Selenium就能抓到。
但Selenium速度慢、资源消耗大。能用requests解决的,优先用requests。Selenium是最后的保底手段。
本篇要点:
- Selenium安装与配置
- 8种元素定位方式
- 输入/点击/下拉框操作
- 显式等待(最重要)
- JavaScript执行
- 窗口和iframe切换
- 实战:Selenium豆瓣爬虫
下一篇学习Cookie与登录态——搞定需要登录才能访问的页面。
收藏 + 关注,专栏更新不迷路!
有问题欢迎评论区留言,大家一起讨论!
标签:Python | Selenium | 浏览器自动化 | JS渲染 | 动态页面 | WebDriver | 反爬虫
更多推荐
所有评论(0)