如果浏览器是无头的,脚本行为会改变

Script behavior changes if browser is headless or not

我在 python(使用 selenium)上写了一个网络抓取程序,效果很好。最后一步是添加无头功能。 问题是当脚本 运行 无头时,在特定时刻(当它应该点击 link 刷新页面时),终端给我这个错误:

selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <a href="javascript:void(0);" onclick="prtl.refresh(this);">...</a> is not clickable at point (217, 157). Other element would receive the click: <span ewnet:toggler="290" class="prtl">...</span>

奇怪的是,当同一个脚本不是无头时,selenium 不会抛出错误并且一切顺利。

我尝试使用多种方法到达该元素,但出现相同的错误。

这是脚本决定浏览器是否无头的时间:

# create driver
if headless:
    chromedriver = './chromedriver'
    options = webdriver.ChromeOptions()
    options.add_argument('headless')
    driver = webdriver.Chrome(executable_path = chromedriver, chrome_options = options)
else:
    driver = webdriver.Chrome('./chromedriver')

我尝试点击的元素看起来像这样:

<a href='some_url' onclick='refresh(this)'>
<span class='name'>refresh page!</span>
</a>

我的脚本通过 <a> 标签上的 xpath 搜索它。

尝试设置 window 大小,即使它是无头的。

我记不太清了,但几年前我在 selenium 上编写端到端测试时遇到了同样的错误。我认为它仍然需要视口大小,如果无头(?),引擎可能默认将其优化为 0x0。

解决方案是确保 window 大小足以让对象可点击,否则 window-size 属性 设置为 0x0,对象将被互相拥抱:

options.add_argument('window-size=2000x1500')

因此代码将如下所示:

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('window-size=2000x1500')

这适用于 chromedriver。我没有检查其他无头浏览器,但期望有相同或相似的行为。