前言
在实习的时候,需要做一些爬虫,所以就接触到了Selenium
再开始就使用调用接口,所以需要去逆向找RSA加密算法的key,或者其他加密的东西
后面发现,不管是黑猫还是白猫,抓到老鼠就是好猫
逆向网页这玩意,我是真不懂,又没有兴趣去研究
所以还是大道至简,直接用Selenium抓取网页数据吧,简单方便!
一、Selenium是什么
Selenium是一个用于自动化web应用程序测试的工具。它提供了一组工具和库,可以用多种编程语言(如Java、Python、C#等)编写测试脚本,模拟用户在浏览器中的行为,如点击链接、填写表单、提交数据等。Selenium可以在各种浏览器上运行,包括Chrome、Firefox、Safari等,它还可以与其他测试框架和工具集成,帮助开发人员和测试人员自动化执行各种测试任务,提高测试效率和质量。
官网:
SeleniumSelenium automates browsers. That's it!https://www.selenium.dev/**Selenium是支持多种语言的**
这里只说关于Python的
二、Python安装Selenium
1、安装Selenium第三方库
我习惯用4.6低版本的
# 换源 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple # 安装我这个版本 pip install selenium==4.6.0 # 安装默认最新版本 pip install selenium
下载Selenium后,我们需要他来打开浏览器,
但是Selenium需要有浏览器驱动,才可以打开浏览器
2、下载浏览器驱动
下面是Selenium目前支持的浏览器
这里只介绍如何下载谷歌浏览器的驱动,因为我只用过谷歌浏览器的
先确定自己的谷歌浏览器的版本
打开谷歌浏览器,输入地址:
chrome://settings/help
可以查看自己的版本:
选择对应版本号的驱动版本
下载地址:
https://chromedriver.storage.googleapis.com/index.html这里记录下最新版本谷歌驱动器下载地址:
https://googlechromelabs.github.io/chrome-for-testing/我这里打包上传了几个版本的驱动,有需要的,自取:
2024-5-最近几个版本的谷歌浏览器驱动.zip - 蓝奏云文件大小:46.9 M|https://wwm.lanzout.com/iNYDd20cs3ef
3、使用Python来打开浏览器
一般情况下,一些博主推荐存放在python的安装路径
那个只能说方便了我们自己使用,可以快速跑代码demo
但是,当我们需要项目打包,在其他电脑上运行的时候,浏览器驱动放哪里?
这就是一个问题!
所以我们需要实现设置好驱动的路径
我就是直接放在D盘了
运行代码demo
from selenium import webdriver # 设置Chrome浏览器驱动程序的路径 chrome_driver_path = "D:\\chromedriver.exe" # 初始化Chrome浏览器 browser = webdriver.Chrome(executable_path=chrome_driver_path) # 打开百度网页 browser.get("https://www.baidu.com") # 这里可以编写其他与页面交互的代码 # 关闭浏览器 browser.quit()
当我们看见百度网页后,浏览器就会关闭,这样就说明我们设置完成了
三、Selenium的初始化
当我们创建浏览器驱动对象的时候,他会创建一个新的干净的浏览器,来供我们使用
from selenium import webdriver # 设置Chrome浏览器驱动程序的路径 chrome_driver_path = "D:\\chromedriver.exe" # 初始化Chrome浏览器 browser = webdriver.Chrome(executable_path=chrome_driver_path)
所以,我们在浏览器上设置的东西,也可以通过代码实现设置好
比如:
- 浏览器下载文件后,下载的地址设置
- 浏览器是否加载图片
- 浏览器是否禁用JS
- 浏览器是否使用隐私模式
- 浏览器是否使用缓存
等等...
因此,我们可以实现封装一个类,来实现浏览器的初始化
我写的一个简单类,可以通过json文件来修改参数
比如:
获取驱动的路径(在打包后,我们的驱动也需要在生产环境中,让程序可以找到,这时候我们灵活修改)
是否加载图片
是否使用缓存
等等
下面的代码,只适用4.8以下低版本的哟~
# -*- coding: utf-8 -*- # @Author : pan # @Description : 获取浏览器驱动模块 # @Date : 2024年5月25日17:53:17 ''' # # 无界面化. # chrome_opt.add_argument('--headless') # # 配合上面的无界面化. # chrome_opt.add_argument('--disable-gpu') # 设置窗口大小, 窗口大小会有影响. # chrome_opt.add_argument('--window-size=1366,768') # 不加载图片, 提升速度 # chrome_opt.add_argument('--blink-settings=imagesEnabled=false') # # 使用沙盒模式运行 # chrome_opt.add_argument("--no-sandbox") # 远程操控 # chromedriver = webdriver.Remote(_chromedriverUrl, options=chrome_opt) # 自动接受警告和对话框 # chrome_opt.add_argument('--auto-open-devtools-for-tabs') # 忽略SSL错误:对于测试环境中自签名证书的站点。 chrome_opt.add_argument('--ignore-certificate-errors') # chromedriver.set_page_load_timeout(30) # 设置页面加载超时时间 # chromedriver.execute_cdp_cmd("Page.setCacheDisabled", {"cacheDisabled": True}) # 禁用缓存 # 自定义Chrome的数据存储目录,用于持久化Cookies、存储等。 # chrome_opt.add_experimental_option('prefs', {'profile.default_content_settings.popups': 0, # 'download.default_directory': '/path/to/download'}) # # 创建一个临时目录来存储浏览器会话的数据 # user_data_dir = "/path/to/temp/dir" # 替换为你希望存储临时数据的路径 # if os.path.exists(user_data_dir): # shutil.rmtree(user_data_dir) # 如果目录已存在,则删除它 # os.makedirs(user_data_dir) # 创建新的临时目录 # # chrome_opt.add_argument(f"user-data-dir={user_data_dir}") # 设置代理 # chrome_opt.add_argument('--proxy-server=http://ip:port') # chrome_opt.add_argument('--proxy-server=http://127.0.0.1:8888') # 启动无痕模式 # chrome_opt.add_argument('--incognito') # 禁用扩展 # chrome_opt.add_argument('--disable-extensions') # 禁用JS # chrome_opt.add_argument('--disable-javascript') # 用户代理设置:模拟不同的浏览器或设备访问。 # chrome_opt.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3') ''' import time import json import os from dataclasses import dataclass, asdict from selenium import webdriver @dataclass class WebDriveConf: """ 浏览器驱动配置 """ chromedriver_url: str = 'D:\\chromedriver.exe' # 浏览器驱动路径 user_data_dir: str = 'D:\\webDriverTempDir' # 存储临时数据的路径 is_use_cache: int = 0 # 是否使用缓存 is_load_page: int = 1 # 是否加载页面 is_load_img: int = 0 # 是否加载图片 is_ignore_certificate: int = 1 # 是否忽略证书 is_incognito: int = 1 # 是否启动无痕模式 def to_dict(self) -> dict: """ 返回配置信息的 JSON 格式表示 Returns: dict: 配置信息的 JSON 格式表示 """ return asdict(self) def read_json_config(self, file_path: str) -> dict: """ 从 JSON 文件中读取配置信息并返回字典 Args: file_path (str): JSON 文件路径 Returns: dict: 包含配置信息的字典 """ # 检查文件是否存在 if not os.path.exists(file_path): # 如果文件不存在,则创建一个包含默认配置信息的 JSON 文件 with open(file_path, "w") as file: json.dump(self.to_dict(), file, indent=4) # 读取配置文件 with open(file_path, "r") as file: config_dict = json.load(file) return config_dict def write_json_config(self, config_dict: dict, file_path: str): """ 将配置信息写入 JSON 文件 Args: config_dict (dict): 包含配置信息的字典 file_path (str): JSON 文件路径 """ with open(file_path, "w") as file: json.dump(config_dict, file, indent=4) class ChromeWebDriver: def __init__(self, conf: WebDriveConf): self.conf = conf self.chrome_opt = webdriver.ChromeOptions() self.chrome_opt.add_argument('--user-data-dir=' + self.conf.user_data_dir) # 判断是否使用缓存 (如果不使用缓存,则删除缓存文件) if not self.conf.is_use_cache: if os.path.exists(self.conf.user_data_dir): # 删除这个文件夹 import shutil shutil.rmtree(self.conf.user_data_dir) # 判断是否有文件夹 if not os.path.exists(self.conf.user_data_dir): os.makedirs(self.conf.user_data_dir) # 无界面化 if not self.conf.is_load_page: self.chrome_opt.add_argument('--headless') # 是否加载图片 if not self.conf.is_load_img: self.chrome_opt.add_argument('--blink-settings=imagesEnabled=false') # 是否忽略证书 if self.conf.is_ignore_certificate: self.chrome_opt.add_argument('--ignore-certificate-errors') # 启动无痕模式 if self.conf.is_incognito: self.chrome_opt.add_argument('--incognito') # 创建 Chrome WebDriver 实例 self.chromedriver = webdriver.Chrome(executable_path=self.conf.chromedriver_url, options=self.chrome_opt) if __name__ == '__main__': # 创建 WebDriveConf 实例并解包配置信息 web_driver_conf = WebDriveConf(**WebDriveConf().read_json_config("web_driver_conf.json")) # 创建 ChromeWebDriver 实例 chrome_web_driver = ChromeWebDriver(web_driver_conf) # 打开网页 chrome_web_driver.chromedriver.get("https://www.bilibili.com/?spm_id_from=333.788.0.0") time.sleep(10) chrome_web_driver.chromedriver.quit()
四、Selenium获取网页元素
首先,我们需要了解网页的结构,打开网页按F12,或者右键页面,然后点击【检查】
即可看见到我们的开发者界面
就可以html代码了,那个元素就想树形图一样的排列,所以我们获取的方法有很多种
现在默认你有前端的基础,了解HTML
当我们打开了网页,我们就可以获取网页上的任何东西
当然,一般我们只需要获取网页上的一些数据信息,文本内容
比如:获取元素中的文本内容
# 通过XPath选择元素 element = driver.find_element_by_xpath("//h1") # 获取元素中的文本 text = element.text print("元素中的文本是:", text)
获取元素的属性内容
# 通过XPath选择元素 element = driver.find_element_by_xpath("//h1") # 获取元素中的class内容 class_content = element.get_attribute("class") print("元素中的class内容是:", class_content)
但是,最关键的一点是我们如何获取这些元素呢?
你如何确定最后的element 是我们想要的那一个呢?
Selenium有很多元素筛选方法,通过class、id等等进行筛选
下面就是常见方法
但是还是最推荐用xpath
可以直接下图方法使用这个来获取这个元素的路径
但是我更喜欢自己手动找元素!
4.1、获取元素的实用方法
打开网页后,我们就需要和里面的元素进行交互,所以我们要获取
1、模糊匹配获取元素 & 联合多个样式
main_line_list = chromedriver.find_elements(By.XPATH, f"//span[@class='fancytree-title' and contains(@title, '干线')]")
这里既筛选了class中的内容,又筛选了这个span标签里面的文本信息
其实,一般情况下,我们可以直接模糊匹配内容就足够了!
也就是直接使contains!!!所以这就是为什么建议使用xpath了
2、使用拉姆达表达式
这样可以更加直观的看出代码含义
element = WebDriverWait(chromedriver, timeout=10). until(lambda d: d.find_element(By.ID, "tree-input"))
3、加上睡眠时间,增加容错
当浏览器点击了一些东西之后,他需要加载或者跳转网页
所以我们需要让程序睡眠一下,增加容错
尤其是,我实习的那里,那些电脑都是老古董,时不时就抽风,卡顿...
chrome_web_driver.chromedriver.find_element(By.XPATH, "//span[text()='重置密码']").click() time.sleep(2)
4、合理利用树形结构
有时候,我们定位一个元素,往往会有多个重复的元素
我们可以先获取他的祖先元素,在祖先元素的基础上,再进行获取!
chromedriver.find_element(By.ID, 'colid-1934886344377413') .find_element(By.CLASS_NAME, "suffix-group")
5、获取多个元素
当我们需要批量操作时,就可以获取多个元素
或者,当我们懒得去找某一个元素的关键特征时,我们可以获取多个
再遍历多个元素,去找到我们需要的那一个元素!
同时,像登录页中,一般就两个input元素
我们就可以直接获取,再根据代码找元素的顺序,是从根节点开始查找的
所以,一般第一个输入框就是输入账号,第二个输入框就是输入密码
input_elements = chromedriver.find_elements(By.TAG_NAME, 'input') print(len(input_elements)) # 输入账号 & 密码 input_elements[0].clear() input_elements[0].send_keys(username) time.sleep(1) input_elements[1].clear() input_elements[1].send_keys(password)
获取多个元素,批量进行操作:
# 获取 多个 线段 overhead_line = chromedriver.find_elements(By.XPATH, f"//span[@class='fancytree-title' and @title='架空线段']") time.sleep(3) # 尝试点击多个线段 for line in overhead_line: line.click()
4.2、获取网页元素失败怎么办?
1、确保4.1的方法都使用正确!!
可能是获取到了多个
确保使用正确的定位方式来定位元素。
可以采用4.1中的方法
2、检查我们的代码,获取的那个代码,是否有问题
看清楚元素是div还是span,还是
我之前就是因为这个,在那里找了半天的错误
3、iframe的问题
网页中的iframe(内联框架)是页面中嵌套的独立文档。
在Selenium中,要与iframe中的元素进行交互,需要先切换到iframe上下文,然后才能执行操作。
定位iframe元素
iframe = driver.find_element_by_xpath("//iframe[@id='frame_id']")
切换到iframe上下文
driver.switch_to.frame(iframe)
执行在iframe中的操作
element_inside_iframe = driver.find_element_by_xpath("//button[@id='button_inside_iframe']") element_inside_iframe.click()
切换回默认上下文
driver.switch_to.default_content()
如果iframe嵌套层级较深,你可能需要多次切换上下文来定位内部的iframe和元素。在处理复杂的页面结构时,建议先仔细分析页面结构,确保准确地切换到所需的iframe上下文。
dialog_iframe = chromedriver.find_elements(By.TAG_NAME, "iframe") chromedriver.switch_to.frame(dialog_iframe[4])
4、网页跳转的问题
当我们进行了网页的一些操作时,会打开新的网页,这时候,我们还停留在原来的网页!
我们需要切换到新的网页里面进行操作的话,也得进行切换!!!
获取当前窗口句柄
current_window_handle = driver.current_window_handle
获取所有窗口句柄
all_window_handles = driver.window_handles
切换到新窗口句柄
for window_handle in all_window_handles: if window_handle != current_window_handle: driver.switch_to.window(window_handle) break
切换回原始窗口句柄(可选)
driver.switch_to.window(current_window_handle)
五、Selenium点击元素的方法
当我们可以获取元素后,我们往往需要进行操作,其中无非就是输入+点击
输入很简单,我们只需要3行代码
input_element = chromedriver.find_element(By.ID, 'findSource').find_element(By.TAG_NAME, 'input') input_element.clear() input_element.send_keys('无人机')
为了避免有错误,在输入前最好先清空一下里面的内容
使用右键点击
canvas_element = chromedriver.find_element(By.TAG_NAME, 'canvas') ActionChains(chromedriver).context_click(canvas_element).perform()
下面的都是左键的点击方法了
方法描述
click()
方法使用 Selenium 提供的
click()
方法直接触发元素的点击事件。JavaScript 执行点击事件使用
driver.execute_script()
方法执行 JavaScript 代码,模拟触发点击事件。ActionChains 类使用
ActionChains
类提供的方法模拟用户操作,包括点击操作。
send_keys(Keys.RETURN)
方法对于某些元素,可以使用
send_keys(Keys.RETURN)
方法模拟按下回车键,从而触发点击事件。
submit()
方法如果要点击的元素是一个表单中的提交按钮,可以直接使用
submit()
方法来提交表单,触发点击事件。使用 JavaScript 修改元素属性通过执行 JavaScript 代码来修改元素的属性,例如将元素的
onclick
属性设置为
null
,然后再点击该元素。使用
pyautogui
或
Robot
类在某些情况下,可以使用
pyautogui
或
Robot
类来模拟鼠标点击,从而触发点击事件。
在 Selenium 中触发点击事件(最常用的三种方法)
1、使用 click() 方法:
这是最简单和最常用的方法。通过选中要点击的元素,然后使用 click() 方法来触发点击事件。
示例代码:element = driver.find_element_by_id("element_id") element.click()
2、使用 JavaScript 执行点击事件:
有时候使用 Selenium 的 click() 方法可能不够稳定,可以通过执行 JavaScript 代码来模拟点击事件。
示例代码:element = driver.find_element_by_id("element_id") driver.execute_script("arguments[0].click();", element)
3、使用 ActionChains 类:
ActionChains 类提供了模拟用户行为的方法,其中包括鼠标点击操作。
示例代码:from selenium.webdriver.common.action_chains import ActionChains element = driver.find_element_by_id("element_id") ActionChains(driver).click(element).perform()
这些方法可以根据具体情况和需求选择合适的方式来触发点击事件。通常情况下,推荐优先使用 click() 方法,如果出现稳定性问题,可以尝试使用 JavaScript 执行点击事件或者 ActionChains 类来解决。
另外四种(不常用)
4、使用 send_keys(Keys.RETURN) 模拟回车键:
对于某些元素,可以使用 send_keys(Keys.RETURN) 方法来模拟按下回车键,从而触发点击事件。
示例代码:element = driver.find_element_by_id("element_id") element.send_keys(Keys.RETURN)
5、使用 submit() 方法提交表单:
如果要点击的元素是一个表单中的提交按钮,可以直接使用 submit() 方法来提交表单,触发点击事件。
示例代码:form = driver.find_element_by_id("form_id") form.submit()
6、使用 JavaScript 修改元素属性:
可以通过执行 JavaScript 代码来修改元素的属性,从而触发点击事件。例如,将元素的 onclick 属性设置为 null,然后再点击该元素。
示例代码:element = driver.find_element_by_id("element_id") driver.execute_script("arguments[0].setAttribute('onclick', 'null');", element) element.click()
7、使用 Robot 类模拟物理点击:
在某些情况下,可以使用 Python 的 pyautogui 或 Java 的 Robot 类来模拟鼠标点击,从而触发点击事件。
示例代码(Python pyautogui):import pyautogui element = driver.find_element_by_id("element_id") element_location = element.location pyautogui.click(element_location['x'], element_location['y'])
这些方法可以根据具体情况和需求来选择合适的方式来实现点击事件。需要注意的是,每种方法都有其适用的场景和限制条件,选择时应根据具体情况进行权衡和判断。
六、Selenium+browsermob-proxy获取网络请求
为什么要获取网络请求,因为有一些数据是渲染到canvas里面的
导致我们从网页中的元素里面拿取不到!那么就只有通过抓请求了!!!
1. 下载browsermob-proxy.bat
Releases · lightbody/browsermob-proxy · GitHubA free utility to help web developers watch and manipulate network traffic from their AJAX applications. - Releases · lightbody/browsermob-proxyhttps://links.jianshu.com/go?to=https%3A%2F%2Fgithub.com%2Flightbody%2Fbrowsermob-proxy%2Freleases**要求jdk1.8以上**
下载JDK,可以直接使用Java8安装!
java8安装教程:
java 8( jdk1.8u321)安装教程(超详细)_java8安装-CSDN博客
2.安装python模块browsermob-proxy
pip install browsermob-proxy
3、编写代码
import time from selenium import webdriver from browsermobproxy import Server # 启动 browsermob-proxy 服务器 server = Server(r"D:\browsermob-proxy-2.1.4\bin\browsermob-proxy.bat") server.start() proxy = server.create_proxy() # 配置 Selenium WebDriver 使用代理 proxy_address = "--proxy-server={0}".format(proxy.proxy) chrome_options = webdriver.ChromeOptions() chrome_options.add_argument(proxy_address) chrome_options.add_argument('--ignore-certificate-errors') driver = webdriver.Chrome(chrome_options=chrome_options) # 开始记录网络请求 proxy.new_har("page") # 打开网页 driver.get("https://baidu.com") time.sleep(3) # 获取捕获的网络请求 har = proxy.har # 打印请求和响应内容 for entry in har['log']['entries']: request_url = entry['request']['url'] response = entry['response'] response_content = response print("Request URL:", request_url) print("Response Content:", response_content) time.sleep(3) # 关闭浏览器和 proxy 服务器 driver.quit() server.stop()
版权归原作者 Pan_peter 所有, 如有侵权,请联系我们删除。