我想使用Selenium ChromeDriver并行执行搜寻器。
如果在ForEach
循环中使用相同的ChromeDriver实例,则会遇到问题。
当尝试访问HTML文档的属性时,出现异常:
OpenQA.Selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
可能是因为另一个线程在当前线程读取实例之前修改了实例的状态。
这是我现在拥有的:
public class ChromeCrawler : IDisposable
{
private readonly ChromeDriver _driver;
public ChromeCrawler()
{
var chromeOptions = new ChromeOptions();
chromeOptions.AddArguments("headless");
_driver = new ChromeDriver(chromeOptions);
}
public string GetHTML(string url)
{
_driver.Navigate().GoToUrl(url);
var html = _driver.FindElementsByTagName("html");
var content = html.First().GetAttribute("innerHTML"); //<----- Here I get the exception
return content;
}
....
}
var crawler = new ChromeCrawler();
//Execution
Parallel.ForEach(pages_list, page_url =>
{
var html = crawler.GetHTML(page_url );
.....
});
是否可以为ChromeCrawler
的每个线程创建Parallel.ForEach
的新实例?
答案 0 :(得分:0)
将驱动程序存储在单独类别的列表中,以跟踪当前并行执行的所有驱动程序。就我而言,我有一个名为BrowserController的类,该类跟踪当前的驱动程序实例并处理驱动程序的创建和删除。它使用如下函数添加新的驱动程序:
public Dictionary<string, RemoteWebDriver> Drivers;
public RemoteWebDriver AddDriver(string testName, string url, ICapabilities capabilities)
{
var driver = new ThreadLocal<RemoteWebDriver>(() =>
{
return new RemoteWebDriver(new Uri(url), capabilities);
}).Value;
Drivers.Add(testName, driver);
TestBase.StaticLogInfo($"Added driver for test: {testName}");
return Drivers[testName];
}