python零基础-写爬虫(selenium)-001

92 阅读5分钟

背景:本人不爱看java八股文,也不喜欢深入研究源码,技术栈三年未更新,简历一言难尽,且java业务快写吐了,最近迷上python语言,此时公司需要使用爬虫获取一些数据,因此开始使用python编写爬虫脚本,因公司合规要求:爬取数据需模拟浏览器点击方式,因此使用selenium开源工具,python环境的安装配置这里就不一一叙述,python基础语法目前是看B站业余时间学习(进度-看了不到一周),最后deepseek很好用。

一、Selenium是什么?

Selenium 是一个用于 自动化 Web 浏览器操作 的开源工具套件,主要用于 Web 应用的自动化测试,但也常用于网络爬虫、数据抓取和重复性网页操作自动化等领域。它支持多种编程语言(如 Python、Java、C#、JavaScript 等)和主流浏览器(Chrome、Firefox、Edge、Safari 等),是 Web 自动化领域的标杆工具。

二、Selenium核心组件

1.Selenium IDE(需要翻墙,这个插件好像被禁用啦)

浏览器插件形式的录制回放工具

适合快速生成测试用例

支持导出为Python/Java等代码

2.Selenium WebDriver

主流编程语言(Python/Java/C#/JavaScript等)的API

直接控制浏览器底层驱动

支持Chrome、Firefox、Edge等主流浏览器

3.Selenium Grid

分布式测试执行框架

支持并行运行测试用例

跨平台、跨浏览器测试

三、工作原理

开发者编写自动化脚本 →

WebDriver将指令转换为HTTP请求 →

浏览器驱动(如ChromeDriver)接收指令 →

真实浏览器执行操作 →

返回执行结果

四、关键技术点

1.元素定位策略

推荐使用:xpath

ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
2.等待机制

显式等待(推荐)

from selenium.webdriver.support.ui import WebDriverWait
element = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.ID, "dynamicElement"))
)

隐式等待

implicitly_wait是Selenium WebDriver提供的一种全局等待策略,用于设置查找页面元素时的最大等待时间。当尝试定位元素时,若元素未立即出现,WebDriver会在指定时间范围内持续轮询DOM,直到找到元素或超时。
driver.implicitly_wait(5)  # 隐式等待,全局有效

线程等待 python

time.sleep() 
3高级功能.
执行JavaScript:driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
文件上传/下载处理
浏览器窗口/标签页管理

五.优势与局限

优点:

完全免费开源,社区活跃。

支持多语言、多浏览器

支持复杂交互(如拖拽、弹出框处理)。

可结合代理、无头模式(Headless)适应不同需求。

缺点:

只支持PC端,无法处理桌面应用

动态内容加载需额外等待,执行速度较慢(相比直接 HTTP 请求)。

需安装浏览器和对应驱动,环境配置稍复杂。

动态内容可能导致元素定位不稳定(需配合显式等待等机制)。

验证码等安全机制需绕道处理

环境配置 python + chrome + chrome_driver

python
版本:3.13.2 
lvchunfeng@lvchunfengs-MacBook-Pro python-project % python3
Python 3.13.2 (v3.13.2:4f8bb3947cf, Feb  4 2025, 11:51:10) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
chrome浏览器:

本机已经升级最新的版本版本 134.0.6998.45(正式版本) (x86_64)

chrome_driver

需要根据chrome浏览器下载对应版本的驱动 下载参考博客:blog.csdn.net/Sheri996/ar…

webDriver 初始化
options = webdriver.ChromeOptions()
options.add_argument("--headless")  # 屏蔽调试的浏览器
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)
简单的demo
import time

from lxml.etree import XPath
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from selenium.common.exceptions import TimeoutException, NoSuchElementException

from bs4 import BeautifulSoup
import platform
import logging
import pandas as pd

options = webdriver.ChromeOptions()
options.add_argument("--headless")  # 屏蔽调试的浏览器
options.add_argument("--disable-gpu")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)

driver.get("https://fanyi.youdao.com")

driver.implicitly_wait(20)  #

print(driver.current_url)
print(driver.title)

try:
    close = driver.find_element(By.XPATH, "/html/body/div[8]/div/img[2]")
    close.click()
    driver.implicitly_wait(3)
except Exception as ec:
    print("关闭错误")
translate = driver.find_element(By.XPATH,
                                "//*[@id=\"app\"]/div[1]/div/div[2]/div[2]/div[2]/div/div/div[1]/div[1]/div[1]")
translate.click()

driver.implicitly_wait(5)

input = driver.find_element(By.XPATH, "//*[@id=\"js_fanyi_input\"]")
input.send_keys("学习")
time.sleep(10)
driver.implicitly_wait(10)
input = driver.find_element(By.XPATH, "//*[@id=\"js_fanyi_output\"]")
print(input.text)
driver.implicitly_wait(60)

遇到的难点:

1.文件下载拦截:
下载文件时,遇到文件下载一直被拦截,查询很多解决方案,最后时修改配置参数,信任域名。
webDriver初始化时,信任域名
options.add_argument(
"--unsafely-treat-insecure-origin-as-secure=XXXXXXXX(域名)")
2.frame页面切换:

刚开始不知道需要切换frame 使用Xpath路径定位元素一直定位失败。

3.Xpatch 路径动态ID

需要专门学习Xpath路径语法,可以将完整的Xpath路径发给deepseek,它会给你一个模糊匹配的Xpath路径
 iframe_xpath = "//iframe[contains(@src, 'dispatchOrderManagement')]"
4.滑动验证码识别

登录时出现滑动验证码验证。 主要使用python的cv2图片识别,找到移动的位置,识别精度度不是很高,增加重试机制。

def _get_pos(image_path):
    """检测图像中符合特定条件的轮廓位置"""
    image = cv2.imread(image_path)
    if image is None:
        print("错误:无法读取图像文件")
        return 0
    # 增加灰度转换和二值化处理
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV)
    # 预处理流程
    blurred = cv2.bilateralFilter(gray, 9, 75, 75)
    # 动态计算Canny阈值
    median = np.median(blurred)
    sigma = 0.33
    lower = int(max(0, (1.0 - sigma) * median))
    upper = int(min(255, (1.0 + sigma) * median))
    edges = cv2.Canny(blurred, lower, upper)
    # 轮廓检测(仅检测外部轮廓)
    contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    max_area = 500  # 最小有效面积阈值
    target_x = 0
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        area = cv2.contourArea(contour)

        # 强化筛选条件 and (area > max_area) and (cv2.isContourConvex(contour))
        if (0.8 < w / h < 1.2) and (2000 > area > max_area):
            max_area = area
            target_x = x
            # 绘制检测结果
            cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)

    if target_x:
        cv2.imwrite('./111.png', image)
        return target_x
    return 0

自定义下拉多选:

multi_select = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.XPATH, '//input[@name="fromCode"][@placeholder="请选择"]'))
    )
    ActionChains(driver).click(multi_select).perform()
    wait = WebDriverWait(driver, 10)
    for item in step["select_item"]:
        # 清空输入框
        multi_select.clear()
        # 输入关键词
        multi_select.send_keys(item)
        # 使用正确的XPath引号
        option_xpath = f'//li[contains(@title, "{item}")]'
        try:
            # 显式等待选项出现
            option = wait.until(EC.element_to_be_clickable((By.XPATH, option_xpath)))
            option.click()
        except Exception as e:
            print(f"未查询到: {item}")

    # 使用更安全的关闭方式(如按ESC键)
    ActionChains(driver).send_keys(Keys.ESCAPE).perform()
    time.sleep(10)

获取Xpath路径

现在用的都是使用浏览器copy Xpath路径,路径比较死

image.png

准备使用 TestCase Studio - Selenium IDE 1.8.3 浏览器插件 (需要翻墙)

目前还在摸索阶段

最后: 已成功爬取三个网站数据,但是脚本代码写的比较乱,且脚本写的不够健壮,在思考整理代码,将操作节点做成可配置的。