C# Try-catch无法捕获预期的NoSuchElementException问题
Selenium C#爬虫NoSuchElementException捕获失败问题解决
问题描述
我用C#开发了基于Selenium的新闻爬取程序,多数新闻页面顶部包含图片,部分新闻会用视频替代图片,这种场景下需要为其设置默认图片。原代码通过driver.FindElement(By.CssSelector("tbody > tr > td > img"))查找图片元素,不存在时会抛出NoSuchElementException,原本用try-catch块捕获该异常并设置默认图片,但近期未修改代码的情况下,该异常突然无法被捕获,直接变为未处理异常。先后尝试捕获通用Exception、添加专门的NoSuchElementException分支,问题均未解决。
相关代码片段
try { var imageElement = driver.FindElement(By.CssSelector("tbody > tr > td > img")); imageSrc = imageElement.GetAttribute("src"); } catch (NoSuchElementException e) { Console.WriteLine($"Exception when looking for imageElement! {e.Message}"); imageSrc = "https://digitalfinger.id/wp-content/uploads/2019/12/no-image-available-icon-6.png"; } catch (Exception e) { Console.WriteLine($"Exception when looking for imageElement! {e.Message}"); imageSrc = "https://digitalfinger.id/wp-content/uploads/2019/12/no-image-available-icon-6.png"; }
完整方法代码
private News GetTheNewsData(ChromeDriver driver, WebDriverWait wait) { Console.OutputEncoding = Encoding.UTF8; string imageSrc = ""; string date = ""; DateTime dateParsed = DateTime.Now; try { var imageElement = driver.FindElement(By.CssSelector("tbody > tr > td > img")); imageSrc = imageElement.GetAttribute("src"); } catch (NoSuchElementException e) { Console.WriteLine($"Exception when looking for imageElement! {e.Message}"); imageSrc = "https://digitalfinger.id/wp-content/uploads/2019/12/no-image-available-icon-6.png"; } catch (Exception e) { Console.WriteLine($"Exception when looking for imageElement! {e.Message}"); imageSrc = "https://digitalfinger.id/wp-content/uploads/2019/12/no-image-available-icon-6.png"; } try { //Wait for the title element to load wait.Until(ExpectedConditions.ElementExists(By.CssSelector("h1.title"))); //Get the title element var titleElement = driver.FindElement(By.CssSelector("h1.title")); var title = titleElement.Text; //Wait for the date element to load wait.Until(ExpectedConditions.ElementExists(By.CssSelector("div.art_author"))); //Get the date element var dateElement = driver.FindElement(By.CssSelector("div.art_author")); if (dateElement.Text.StartsWith("Обновена")) { var pipeIndex = dateElement.Text.IndexOf('|'); date = dateElement.Text.Substring("Обновена: ".Length, pipeIndex - "Обновена: ".Length).Trim(); Console.WriteLine($"Trimmed date: {date}"); } else { date = dateElement.Text.Split(',')[0]; } try { dateParsed = DateTime.ParseExact(date, "d MMM yyyy HH:mm", new CultureInfo("bg-BG"), DateTimeStyles.None); } catch (Exception e) { Console.WriteLine($"Exception parsing the date! {e.Message}"); dateParsed = new DateTime(1000, 1, 1, 12, 30, 0); } Console.WriteLine(dateParsed.ToString("dd/MM/yyyy HH:mm")); //Wait for the div with content paragraphs to load wait.Until(ExpectedConditions.ElementExists(By.CssSelector("div#art_start"))); //Get the div with content paragraphs var divWithContentParagraphs = driver.FindElement(By.CssSelector("div#art_start")); //Get the content paragraphs var contentParagraphs = divWithContentParagraphs.FindElements(By.CssSelector("p")); var sterilizedParagraphs = SterilizeTheNews(contentParagraphs); var currentNews = new News { Title = title, Content = sterilizedParagraphs, Date = dateParsed, ImageUrl = imageSrc }; return currentNews; } catch (Exception e) { Console.WriteLine($"Exception in getting the news data! {e.Message}"); return null; } }
可能原因及解决方案
1. 命名空间冲突
如果项目中引用了多个包含NoSuchElementException的命名空间,可能导致捕获的异常并非Selenium抛出的实例。
解决办法:捕获异常时指定完整命名空间:
catch (OpenQA.Selenium.NoSuchElementException e) { Console.WriteLine($"查找图片元素出错:{e.Message}"); imageSrc = "默认图片URL"; }
2. 改用FindElements避免异常
FindElement找不到元素时会抛出异常,而FindElements会返回空集合,无需依赖异常捕获,代码更稳定。
解决办法:
var imageElements = driver.FindElements(By.CssSelector("tbody > tr > td > img")); if (imageElements.Any()) { imageSrc = imageElements.First().GetAttribute("src"); } else { Console.WriteLine("未找到图片元素,使用默认图片"); imageSrc = "默认图片URL"; }
3. 排查实际异常类型
捕获通用异常时输出完整堆栈信息,确认实际抛出的异常类型及来源:
catch (Exception e) { Console.WriteLine($"查找图片元素出错:{e.Message}\n堆栈信息:{e.StackTrace}"); imageSrc = "默认图片URL"; }
4. 添加元素等待逻辑
若图片是异步加载,直接执行FindElement可能因元素未加载完成抛出异常,可添加等待逻辑确保元素加载:
try { wait.Until(ExpectedConditions.ElementIsVisible(By.CssSelector("tbody > tr > td > img"))); var imageElement = driver.FindElement(By.CssSelector("tbody > tr > td > img")); imageSrc = imageElement.GetAttribute("src"); } catch (OpenQA.Selenium.TimeoutException) { Console.WriteLine("图片元素加载超时,使用默认图片"); imageSrc = "默认图片URL"; } catch (OpenQA.Selenium.NoSuchElementException e) { Console.WriteLine($"查找图片元素出错:{e.Message}"); imageSrc = "默认图片URL"; }
内容的提问来源于stack exchange,提问作者Alexander Nedelchev
相关产品推荐
相关产品推荐

