selenium禁止页面加载javascript

最近爬取几个页面总是失败,遇到如下错误:

# The HTTP request to the remote WebDriver server for URL http://localhost:xxx/ session timed out after 60 seconds.

后来发现原因是页面加载缓慢,debug发现页面其实已经在浏览器中成功渲染,只是还在等待一些后台javascript加载完毕,然后超时报错。

考虑到许多javascript都是广告、统计等一些附加内容,用selenium爬取页面时仅需要其中的html,无须等待所有javascript加载完毕。因此,想看看如何禁止ChromeDriver加载javascript,仅下载html。

搜了下"Selenium Disable JavaScript in ChromeDriver",发现了几种方案,最终用Page load strategy解决问题,小结一下各种方案的坑。

禁用JavaScript(不好使)

让Chrome禁用javascript应该是最直接的想法,搜了一堆文章,如: How to disable java script in Chrome Driver Selenium Python Disable JavaScript ChromeDriver #6672

var options = new ChromeOptions();
options.AddArgument("disable-javascript");

事实证明,没有一个方案可以真正禁用js,不好使。而且这里AddArgument()中使用的是string,而如何找到可用的string列表本身就是个问题。

设置页面加载超时(不好使)

另一个想法是当页面加载缓慢时让它超时,然后继续执行后续的代码解析已下载的html。 Selenium WebDriver - How to set Page Load Timeout using C#

设置页面加载超时的语法找了半天,因为许多文章都是过时的,找到目前可用的语法如下:

driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(30);

但页面超时之后并不像想像当中那样继续执行后续代码,而是抛出了异常进入了catch块,所以并不能解析已加载的html。

用ExecuteScript(不好使)

于是又找到了 How do I set the selenium webdriver get timeout?

本来使用用driver.Navigate().GoToUrl(url)来加载页面,这里提示可以用ExecuteScript()替代它解决问题:

//driver.Navigate().GoToUrl(url);

driver.ExecuteScript($"window.location.href='{url}'");

试验后发现失败率少了一些,不过执行ExecuteScript并不像描述的那样马上返回,依然会出现加载失败的情况。感觉二者在本质上没有区别,没能get到此方案的优越性。

设置页面加载策略

参考如下两篇文章: Page load strategy for Chrome driver (Updated till Selenium v3.12.0)

WebDriver W3C - Page load strategy

Page load strategy有三种:默认是normal,即等着全部页面加载完毕;none的话是把html下载完毕;eager模式则中庸一些,html下载并解析完毕。原文参考:


  1. normal This stategy causes Selenium to wait for the full page loading (html content and subresources downloaded and parsed).

  2. eager This stategy causes Selenium to wait for the DOMContentLoaded event (html content downloaded and parsed only).

  3. none This strategy causes Selenium to return immediately after the initial page content is fully received (html content downloaded). ---

为达到“禁用javascript”,经尝试eager策略最为合适。none的话,使用FindElementByXXX()方法常常定位不到需要查找的内容,有些过于激进。eager策略完美解决禁用js的问题。代码如下:

var options = new ChromeOptions();
options.PageLoadStrategy = PageLoadStrategy.Eager;
...

using (var driver = new ChromeDriver(driverService, options))
{
     driver.Navigate().GoToUrl(url);
     ...
}