Selenium 无头模式 vs 非无头模式

4

我目前正在使用Python中的Selenium进行网页抓取项目。

当在非无头模式下从Web驱动程序运行代码时,我的代码按预期工作。但是,在无头模式下运行时,则不是这种情况。例如,如果我尝试从网站提取文本,则非无头模式将返回文本,而无头模式将返回无结果(None)。 (我已经包含了下面的一些代码以供参考)。

首先,我使用以下代码构建了webdriver(opt.headless设置为True或False,以便在无头和非无头之间切换)。

def getHeadlessDriver():
     opts = webdriver.ChromeOptions()
     opts.headless = False
     driver = webdriver.Chrome(ChromeDriverManager().install(), options=opts)
     return driver

然后,我使用了 find_elements_by_xpath 函数从一个网站中提取文本数据。以下是一段示例代码:

driver = getHeadlessDriver()
feedbacks = driver.find_elements_by_xpath(
    "//div[contains(@class, 'LiveFeedbackSectionViewController__LiveFeedbackStatusItem-sc-1ahetk9-4 cUJPkM')]")
for feedback in feedbacks:
     print(feedback.text)

我通过谷歌搜索尝试找到有关无头模式为什么不起作用的解释,但我还不确定。据我理解,无头模式“行为相同”,只是没有图形用户界面。
我的代码实现可能存在问题吗?或者说,除了没有图形用户界面之外,无头模式还有其他不同之处吗?
谢谢。

你在 getHeadlessDriver 后面缺少了括号。将其更改为 getHeadlessDriver(),它就应该可以工作了 :D - Leyla Zwolinski
缺少的括号是一个笔误,抱歉。除了 GUI 之外,无头和非无头函数是否相同? - checodes
1
有一些调皮的网站在无头模式下不会加载完整页面。为了调试无头模式下网站的差异,我建议您使用 driver.save_screenshot(),然后查看图像以确定页面是否已正确加载。 - Hammad
3个回答

2

我通常可以通过 time.sleep(10) 来解决这个问题,但是我遇到了一个特殊的网站,即使使用 time.sleep(10) 或者 driver.implicitly_wait(10) 也无法爬取。

我认为该网站有一个系统来检查浏览器的用户代理。

为了尝试绕过这个问题,我将用户代理添加到了无头窗口中,并且它起作用了。

browser_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'

options_edge.add_argument(f'user-agent={self.user_agent}')

您可以从像这样的网站获取您的用户代理:https://whatmyuseragent.com/(非关联)。

我的问题与这个问题无关,但使用 user_agent 解决了问题。 - sunnyinho

2
如果您尝试爬取的网站包含由JavaScript渲染的动态元素,则需要使用Xvfb。
sudo apt-get install -y xvfb

"Xvfb或虚拟帧缓存是实现X11显示服务器协议的显示服务器。与其他显示服务器不同的是,Xvfb将所有图形操作都在虚拟内存中执行,而不显示任何屏幕输出。"

在Python中,有两个Xvfb的包装器。

1- xvfbwrapper

pip install xvfbwrapper

然后在你的Python文件中添加:
from xvfbwrapper import Xvfb

display = Xvfb()
display.start()

2- pyvirtualdisplay

pip install PyVirtualDisplay

然后在您的代码中:

from pyvirtualdisplay import Display

display = Display(visible=0, size=(1024, 768))
display.start()

1
我认为我找到了解决这个问题的潜在答案。
在Selenium中使用无头浏览器时,比使用非无头浏览器更快。在这种情况下,Python程序可能在DOM完全加载之前就执行了。
换句话说,试图访问Web元素的函数可能会返回None,因为在调用函数之前这些元素尚未加载。
为解决这个问题,我们可以利用Selenium中包括的implicitly_wait函数。例如:
driver = webdriver.Chrome()
driver.implicitly_wait(3) #units in seconds

将指定的时间(以秒为单位)传递给implicitly_wait函数,告诉驱动程序等待DOM加载。

我已经使用这种方法在无头模式下测试了我的函数,目前似乎可以工作。但如果有其他解决此问题的方法,请随时发表评论!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接