1.用到的程序包(NuGet搜这两个即可,自己看版本)
2.配置部分:
public void StartBrowser()
{
ChromeOptions options = new ChromeOptions();
// 指定缓存目录
string cacheDirectory = System.Environment.CurrentDirectory + @"\cache";
if (!Directory.Exists(cacheDirectory))
{
Directory.CreateDirectory(cacheDirectory);
}
options.AddArgument($"--user-data-dir={cacheDirectory}");
//隐身模式(无痕模式)
options.AddArgument("--incognito");
//取消 chrome正受到自动测试软件的控制的信息栏
options.AddExcludedArgument("enable-automation");
options.AddAdditionalChromeOption("useAutomationExtension", false);
// 设置窗口大小和位置
options.AddArgument("window-size=1280,960"); // 设置窗口大小
options.AddArgument("window-position=0,0"); // 设置窗口位置
// 防止检测为自动化操作
options.AddArgument("--disable-blink-features=AutomationControlled");
options.AddArgument("--disable-infobars");
options.AddArgument("--disable-extensions");
options.AddUserProfilePreference("profile.default_content_setting_values.notifications", 2);
//禁用浏览器的保存密码选项
options.AddUserProfilePreference("credentials_enable_service", false);
//禁用浏览器弹窗(貌似不管用)
options.AddUserProfilePreference("profile.default_content_setting_values.notifications", 2);
//-------------------------------
// 不显示浏览器
//options.AddArgument("--headless");
// GPU加速可能会导致Chrome出现黑屏及CPU占用率过高,所以禁用
//options.AddArgument("--disable-gpu");
// 伪装user-agent
//options.AddArgument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36");
// 禁用图片
//options.AddUserProfilePreference("profile.default_content_setting_values.images", 2);
//指定浏览器配置目录
//string str = System.Environment.CurrentDirectory + "\\selenium\\AutomationProfile";
//options.AddArgument(@"--user-data-dir=" + str);
//指定使用本地浏览器
//options.BinaryLocation = browserAddress;
//options.BinaryLocation = "D:\\develop\\360浏览器\\360se6\\Application\\360se.exe";
//-------------------------------
ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;//关闭黑色cmd窗口
IWebDriver webDriver = new ChromeDriver(driverService, options);
//Selenium事件驱动
eventDriver = new EventFiringWebDriver(webDriver);
// 设置页面加载超时时间
eventDriver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(20);
//如果查找元素在10S内还没有找到.如果你每次点击元素前都使用了 WebDriverWait 来显式等待元素变得可点击,那么不需要再设置隐式等待 (ImplicitWait)。此时,你可以依赖 WebDriverWait 来处理等待逻辑,这样代码更清晰,也避免了不必要的等待时间叠加。如果你希望为所有查找操作设置一个默认的全局等待时间,可以设置 ImplicitWait,但在这种情况下,显式等待应当仅在特定情况下使用,以避免两者的等待时间相互冲突。
//eventDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
//为Selenium添加事件
eventDriver = new EventFiringWebDriver(webDriver);
//eventDriver.Navigating += EventDriver_Navigating;//导航前
eventDriver.Navigated += EventDriver_Navigated;//导航后
//string url = "https://www.baidu.com";
string url = "https://www.google.com/";
try
{
eventDriver.Navigate().GoToUrl(url);
}
catch (WebDriverTimeoutException e)
{
// 页面加载超时,停止加载
IJavaScriptExecutor jsExecutor = (IJavaScriptExecutor)eventDriver;
jsExecutor.ExecuteScript("window.stop();");
}
catch (Exception ex)
{
SetLog($"{DateTime.Now} 发生异常: {ex.GetType().Name}\r\n{ex.Message}\r\n{ex.StackTrace}");
}
// 延时等待页面加载
Thread.Sleep(1000);
// 等待元素出现并点击
wait = new WebDriverWait(eventDriver, TimeSpan.FromSeconds(10));
try
{
IWebElement element = wait.Until(d => d.FindElement(By.CssSelector("a.gb_va.gb_nd.gb_ed.gb_9d")));
element.Click();
}
catch (WebDriverTimeoutException e)
{
var str = string.Format("异常类型:{0}\r\n异常消息:{1}\r\n异常信息:{2}\r\n",
e.GetType().Name, e.Message, e.StackTrace);
SetLog($"{DateTime.Now} 等待元素超时,未找到相应的 a 元素" + str);
}
catch (NoSuchElementException)
{
SetLog($"{DateTime.Now} 元素未找到");
}
catch (Exception ex)
{
SetLog($"{DateTime.Now} 发生异常: {ex.Message}");
}
}
↓↓↓↓↓↓↓↓需要什么事件,这边自己慢慢找↓↓↓↓↓↓↓↓
提示:这边的事件只有在使用eventDriver的进行的操作才会触发,如果你是手动操作的,那么这边的事件是不会被触发的
3.元素操作部分
点击元素
/// <summary>
/// 点击元素
/// </summary>
/// <param name="by"></param>
/// <param name="timeoutInSeconds">等待默认20秒</param>
/// <returns></returns>
public bool ClickElement(By by,int timeoutInSeconds = 20)
{
try
{
// 获取当前时间
var endTime = DateTime.Now.AddSeconds(timeoutInSeconds);
while (isRun && DateTime.Now < endTime)
{
try
{
// 查找元素
IWebElement element = eventDriver.FindElement(by);
// 检查元素是否显示并可交互
if (element.Displayed && element.Enabled)
{
element.Click();
return true; // 点击成功
}
}
catch (NoSuchElementException)
{
//SetLog("元素可能还未加载,继续等待");
}
catch (ElementClickInterceptedException)
{
SetLog($"{by.ToString()} 点击被另一个元素挡住,继续尝试");
}
catch (StaleElementReferenceException)
{
SetLog($"{by.ToString()} 元素不再是当前文档中的一部分,继续尝试");
}
// 等待一段时间后再尝试
Sleep(0.5);
}
// 超时后仍未能成功点击
return false;
}
catch (WebDriverException ex)
{
SetLog($"{by.ToString()} WebDriver 错误: {ex.Message}");
return false;
}
catch (Exception ex)
{
SetLog($"{by.ToString()} 发生未知错误: {ex.Message}");
return false;
}
}
模拟鼠标在指定元素悬停
//模拟鼠标在指定元素悬停
Actions action = new Actions(eventDriver);
var mouserOverlogin = action.MoveToElement(eventDriver.FindElement(By.Id("js_N_nav_login_title"))).Build(); ;
mouserOverlogin.Perform();
如果要点击的元素被其他元素遮挡,报异常,可以用这种方法来点击
var element = webDriver.FindElement(By.Id("mybutton")); //点击写信
((IJavaScriptExecutor)webDriver).ExecuteScript(@"arguments[0].click()", element);
执行JS(将滚动条拉到底部):
//老版执行JS方法
//((IJavaScriptExecutor)webDriver).ExecuteScript("window.scrollTo(0, document.body.scrollHeight)");
//事件驱动执行JS方法
eventDriver.ExecuteScript("window.scrollTo(0, document.body.scrollHeight)");
获取标签(以多Class为例):
ReadOnlyCollection<IWebElement> elements = eventDriver.FindElements(By.CssSelector("[class='item goWork']"));
切换标签页面(eventDriver无法监控当前是在哪个标签页,只能自己SwitchTo)
foreach (string eventDriverWindowHandle in eventDriver.WindowHandles)
{
eventDriver.SwitchTo().Window(eventDriverWindowHandle);
if (eventDriver.Title == "云筑优选-商品详情")
{
downImg();
break;
}
}
退出同时关闭驱动
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// 仅在用户关闭窗口时进行提示
if (e.CloseReason == CloseReason.UserClosing)
{
// 显示退出确认对话框
DialogResult result = MessageBox.Show("确认退出吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (result == DialogResult.OK)
{
// 执行退出前的清理工作
isRun = false;
if (eventDriver != null)
{
// 关闭浏览器并释放资源
eventDriver.Quit();
eventDriver.Dispose();
Thread.Sleep(100); // 确保驱动已关闭
}
//CMD删除缓存文件夹
string cache = System.Environment.CurrentDirectory + @"\cache";
List<string> list = new List<string>() { $"rmdir /s /q \"{cache}\"" };
ExecutionCMDOrders(list, false);
// 允许应用程序退出并退出应用程序
e.Cancel = false;
Application.Exit(); // 确保应用程序退出
}
else
{
// 取消窗口关闭操作
e.Cancel = true;
}
}
else
{
// 对于非用户触发的关闭(如内部调用 Application.Exit()),允许退出
e.Cancel = false;
}
}