来宾市本地咨询网

从入门到精通解析Python Selenium如何模拟浏览器操作

2026-04-01 11:54:02 浏览次数:1
详细信息

从入门到精通:Python Selenium 模拟浏览器操作完整指南

一、Selenium 概述

1.1 什么是 Selenium?

Selenium 是一个用于 Web 应用程序测试的自动化工具,支持多种浏览器和编程语言,通过模拟真实用户操作实现自动化。

1.2 主要组件

二、环境搭建

2.1 安装必要库

# 安装 Selenium
pip install selenium

# 安装浏览器驱动管理器(推荐)
pip install webdriver-manager

2.2 浏览器驱动配置

# 方法1:手动下载驱动(需要匹配浏览器版本)
# Chrome: https://chromedriver.chromium.org/
# Firefox: https://github.com/mozilla/geckodriver/releases

# 方法2:使用 webdriver-manager(自动管理驱动)
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

service = Service(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)

三、基础操作

3.1 启动浏览器

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

# 基础启动
driver = webdriver.Chrome()

# 带配置启动
chrome_options = Options()
chrome_options.add_argument('--headless')  # 无头模式
chrome_options.add_argument('--disable-gpu')  # 禁用GPU
chrome_options.add_argument('--window-size=1920x1080')  # 窗口大小
driver = webdriver.Chrome(options=chrome_options)

# 访问网页
driver.get('https://www.baidu.com')

3.2 元素定位

# 八大定位方式
# 1. ID
element = driver.find_element(By.ID, "kw")

# 2. Name
element = driver.find_element(By.NAME, "wd")

# 3. Class Name
element = driver.find_element(By.CLASS_NAME, "s_ipt")

# 4. Tag Name
elements = driver.find_elements(By.TAG_NAME, "input")

# 5. Link Text(完整链接文本)
element = driver.find_element(By.LINK_TEXT, "新闻")

# 6. Partial Link Text(部分链接文本)
element = driver.find_element(By.PARTIAL_LINK_TEXT, "闻")

# 7. XPath(最常用)
element = driver.find_element(By.XPATH, "//input[@id='kw']")
element = driver.find_element(By.XPATH, "//div[@class='s_form']/form/span[1]/input")

# 8. CSS Selector
element = driver.find_element(By.CSS_SELECTOR, "#kw")
element = driver.find_element(By.CSS_SELECTOR, ".s_ipt")

3.3 常用操作

# 输入文本
search_box = driver.find_element(By.ID, "kw")
search_box.send_keys("Python Selenium教程")
search_box.clear()  # 清空输入框
search_box.send_keys("新的搜索词")

# 点击操作
search_button = driver.find_element(By.ID, "su")
search_button.click()

# 提交表单
search_box.submit()

# 获取元素属性
value = search_box.get_attribute("value")
class_name = search_box.get_attribute("class")

# 获取文本内容
text = driver.find_element(By.XPATH, "//h3").text

# 判断元素状态
is_displayed = search_box.is_displayed()  # 是否显示
is_enabled = search_box.is_enabled()  # 是否可用
is_selected = search_box.is_selected()  # 是否选中(复选框/单选框)

四、高级操作

4.1 等待机制

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# 隐式等待(全局等待)
driver.implicitly_wait(10)  # 最多等待10秒

# 显式等待(针对特定条件)
wait = WebDriverWait(driver, 10)

# 等待元素出现
element = wait.until(EC.presence_of_element_located((By.ID, "kw")))

# 等待元素可点击
element = wait.until(EC.element_to_be_clickable((By.ID, "su")))

# 等待元素可见
element = wait.until(EC.visibility_of_element_located((By.ID, "kw")))

# 等待页面标题包含特定文本
wait.until(EC.title_contains("Python"))

# 常用条件列表
# presence_of_element_located - 元素出现
# visibility_of_element_located - 元素可见
# element_to_be_clickable - 元素可点击
# text_to_be_present_in_element - 元素包含特定文本
# alert_is_present - 弹窗出现

4.2 处理弹窗和警告框

# 获取警告框
alert = driver.switch_to.alert

# 获取文本
alert_text = alert.text

# 接受警告框
alert.accept()

# 拒绝警告框
alert.dismiss()

# 输入文本(prompt类型)
alert.send_keys("输入文本")

# 处理确认框
try:
    alert = driver.switch_to.alert
    alert.accept()  # 点击确定
except:
    print("没有弹窗")

4.3 处理iframe

# 切换到iframe
driver.switch_to.frame("iframe_id")  # 通过id
driver.switch_to.frame("iframe_name")  # 通过name
driver.switch_to.frame(0)  # 通过索引
driver.switch_to.frame(driver.find_element(By.TAG_NAME, "iframe"))  # 通过元素

# 返回主文档
driver.switch_to.default_content()

# 返回上级iframe
driver.switch_to.parent_frame()

4.4 处理多窗口

# 获取当前窗口句柄
current_window = driver.current_window_handle

# 获取所有窗口句柄
all_windows = driver.window_handles

# 切换到新窗口
for window in all_windows:
    if window != current_window:
        driver.switch_to.window(window)
        break

# 关闭当前窗口并切换回原窗口
driver.close()
driver.switch_to.window(current_window)

4.5 执行JavaScript

# 执行JavaScript
driver.execute_script("alert('Hello Selenium');")

# 滚动页面
# 滚动到底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

# 滚动到顶部
driver.execute_script("window.scrollTo(0, 0);")

# 滚动到元素
element = driver.find_element(By.ID, "element_id")
driver.execute_script("arguments[0].scrollIntoView();", element)

# 修改元素属性
driver.execute_script("arguments[0].setAttribute('style', 'color: red');", element)

# 获取页面信息
page_height = driver.execute_script("return document.body.scrollHeight")

4.6 Cookie操作

# 获取所有cookies
cookies = driver.get_cookies()
for cookie in cookies:
    print(cookie['name'], cookie['value'])

# 获取指定cookie
value = driver.get_cookie('cookie_name')['value']

# 添加cookie
driver.add_cookie({'name': 'test', 'value': '123'})

# 删除cookie
driver.delete_cookie('cookie_name')

# 删除所有cookies
driver.delete_all_cookies()

五、实战案例

5.1 自动化登录示例

def login_website(username, password):
    """
    自动化登录示例
    """
    driver = webdriver.Chrome()

    try:
        # 访问登录页面
        driver.get("https://example.com/login")

        # 等待页面加载
        wait = WebDriverWait(driver, 10)

        # 输入用户名
        username_input = wait.until(
            EC.presence_of_element_located((By.NAME, "username"))
        )
        username_input.send_keys(username)

        # 输入密码
        password_input = driver.find_element(By.NAME, "password")
        password_input.send_keys(password)

        # 点击登录按钮
        login_button = driver.find_element(By.XPATH, "//button[@type='submit']")
        login_button.click()

        # 验证登录成功
        wait.until(EC.url_contains("dashboard"))
        print("登录成功!")

        # 保存截图
        driver.save_screenshot("login_success.png")

    except Exception as e:
        print(f"登录失败: {e}")
        driver.save_screenshot("login_error.png")

    finally:
        driver.quit()

# 使用示例
login_website("your_username", "your_password")

5.2 数据爬取示例

def scrape_news():
    """
    爬取新闻网站示例
    """
    driver = webdriver.Chrome()
    driver.get("https://news.baidu.com")

    news_data = []

    try:
        # 等待新闻列表加载
        wait = WebDriverWait(driver, 10)
        news_list = wait.until(
            EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".hotnews a"))
        )

        # 提取新闻信息
        for index, news in enumerate(news_list[:10]):  # 只取前10条
            title = news.text
            link = news.get_attribute("href")

            # 点击进入详情页(新标签页打开)
            news.click()
            driver.switch_to.window(driver.window_handles[-1])

            # 获取详情页内容
            time.sleep(2)  # 等待页面加载
            try:
                content_element = driver.find_element(By.CLASS_NAME, "article-content")
                content = content_element.text[:200]  # 取前200字符
            except:
                content = "无法获取内容"

            news_data.append({
                "序号": index + 1,
                "标题": title,
                "链接": link,
                "内容预览": content
            })

            # 关闭详情页标签,返回列表页
            driver.close()
            driver.switch_to.window(driver.window_handles[0])

    except Exception as e:
        print(f"爬取失败: {e}")

    finally:
        driver.quit()

    return news_data

# 使用示例
data = scrape_news()
for item in data:
    print(f"{item['序号']}. {item['标题']}")

六、高级技巧与优化

6.1 反反爬虫策略

chrome_options = Options()

# 添加用户代理
chrome_options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')

# 禁用自动化标志
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

# 添加其他反检测参数
chrome_options.add_argument('--disable-blink-features=AutomationControlled')

# 使用代理
chrome_options.add_argument('--proxy-server=http://your-proxy:port')

driver = webdriver.Chrome(options=chrome_options)

# 执行JS修改navigator.webdriver属性
driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")

6.2 性能优化

# 禁用图片加载
prefs = {"profile.managed_default_content_settings.images": 2}
chrome_options.add_experimental_option("prefs", prefs)

# 禁用JavaScript(谨慎使用)
chrome_options.add_experimental_option("prefs", {
    'profile.managed_default_content_settings.javascript': 2
})

# 使用无头模式
chrome_options.add_argument('--headless')

6.3 使用Page Object模式

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LoginPage:
    """登录页面对象"""

    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

    # 定位器
    USERNAME_INPUT = (By.NAME, "username")
    PASSWORD_INPUT = (By.NAME, "password")
    LOGIN_BUTTON = (By.XPATH, "//button[@type='submit']")
    ERROR_MESSAGE = (By.CLASS_NAME, "error-message")

    def enter_username(self, username):
        """输入用户名"""
        element = self.wait.until(EC.presence_of_element_located(self.USERNAME_INPUT))
        element.clear()
        element.send_keys(username)
        return self

    def enter_password(self, password):
        """输入密码"""
        element = self.driver.find_element(*self.PASSWORD_INPUT)
        element.clear()
        element.send_keys(password)
        return self

    def click_login(self):
        """点击登录"""
        element = self.driver.find_element(*self.LOGIN_BUTTON)
        element.click()
        return self

    def get_error_message(self):
        """获取错误信息"""
        try:
            element = self.wait.until(EC.visibility_of_element_located(self.ERROR_MESSAGE))
            return element.text
        except:
            return None

# 使用Page Object
driver = webdriver.Chrome()
login_page = LoginPage(driver)
login_page.enter_username("test").enter_password("123").click_login()

七、调试技巧

7.1 截图和日志

import logging
from datetime import datetime

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

class SeleniumHelper:
    def __init__(self, driver):
        self.driver = driver
        self.logger = logging.getLogger(__name__)

    def take_screenshot(self, name=None):
        """截图并保存"""
        if name is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            name = f"screenshot_{timestamp}.png"

        try:
            self.driver.save_screenshot(name)
            self.logger.info(f"截图已保存: {name}")
        except Exception as e:
            self.logger.error(f"截图失败: {e}")

    def find_element_with_log(self, by, value, timeout=10):
        """查找元素并记录日志"""
        try:
            wait = WebDriverWait(self.driver, timeout)
            element = wait.until(EC.presence_of_element_located((by, value)))
            self.logger.info(f"找到元素: {by}={value}")
            return element
        except Exception as e:
            self.logger.error(f"找不到元素: {by}={value}, 错误: {e}")
            self.take_screenshot("element_not_found.png")
            raise

7.2 使用Pytest进行测试

# test_example.py
import pytest
from selenium import webdriver

@pytest.fixture(scope="class")
def driver():
    """测试夹具:创建和关闭浏览器"""
    driver = webdriver.Chrome()
    driver.maximize_window()
    yield driver
    driver.quit()

class TestBaiduSearch:
    """测试类"""

    def test_search(self, driver):
        """测试搜索功能"""
        driver.get("https://www.baidu.com")

        search_box = driver.find_element(By.ID, "kw")
        search_box.send_keys("Selenium自动化测试")

        search_button = driver.find_element(By.ID, "su")
        search_button.click()

        assert "Selenium" in driver.title

    def test_navigation(self, driver):
        """测试导航功能"""
        driver.get("https://www.baidu.com")
        news_link = driver.find_element(By.LINK_TEXT, "新闻")
        news_link.click()

        assert "新闻" in driver.title

八、常见问题与解决方案

8.1 元素定位问题

# 问题:元素无法定位
# 解决方案:
# 1. 增加等待时间
element = WebDriverWait(driver, 20).until(
    EC.presence_of_element_located((By.ID, "element_id"))
)

# 2. 使用不同的定位方式
# 尝试XPath或CSS Selector

# 3. 检查是否在iframe中
driver.switch_to.frame("iframe_name")

# 4. 使用JavaScript查找
element = driver.execute_script("return document.getElementById('element_id');")

8.2 超时问题

# 设置合理的超时时间
driver.set_page_load_timeout(30)  # 页面加载超时
driver.set_script_timeout(30)     # 脚本执行超时

8.3 内存泄漏问题

# 及时关闭不需要的资源
def safe_quit(driver):
    """安全关闭浏览器"""
    try:
        driver.quit()
    except:
        pass
    finally:
        del driver

九、最佳实践

使用显式等待:避免使用 time.sleep() 异常处理:合理使用 try-except 资源管理:确保浏览器正确关闭 代码复用:使用Page Object模式 配置文件:将配置与代码分离 日志记录:记录关键操作和错误 版本控制:保持驱动与浏览器版本匹配 性能监控:关注内存使用和响应时间

十、学习资源

10.1 官方文档

10.2 进阶学习

通过这个完整的指南,你可以从基础到高级逐步掌握 Selenium 的使用。实践是最好的学习方式,建议从简单的自动化任务开始,逐步挑战更复杂的场景。

相关推荐