由于未知错误导致页面崩溃,Python Selenium 会话被删除:无法从选项卡崩溃中确定加载状态

Posted

技术标签:

【中文标题】由于未知错误导致页面崩溃,Python Selenium 会话被删除:无法从选项卡崩溃中确定加载状态【英文标题】:Python Selenium session deleted because of page crash from unknown error: cannot determine loading status from tab crashed 【发布时间】:2021-10-05 08:27:18 【问题描述】:

问题可能是内存使用。页面开始变得非常慢,有时会出现以下错误消息

from bs4 import BeautifulSoup
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import ActionChains


# Set some Selenium Options
options = webdriver.ChromeOptions()
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')

# Webdriver
wd = webdriver.Chrome(executable_path='/usr/bin/chromedriver', options=options)
# URL
url = 'https://www.techpilot.de/zulieferer-suchen?laserschneiden'

# Load URL
wd.get(url)

# Get html
soup = BeautifulSoup(wd.page_source, 'html.parser')
wd.fullscreen_window()


wait = WebDriverWait(wd, 15)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#bodyJSP #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll"))).click()
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "#efficientSearchIframe")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".hideFunctionalScrollbar #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll"))).click()
#wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".fancyCompLabel")))
roaster=wd.find_element_by_xpath('//*[@id="resultTypeRaster"]')
ActionChains(wd).click(roaster).perform()

#use keys to get where the button is
html = wd.find_element_by_tag_name('html')

c=2
for i in range(100):
    html.send_keys(Keys.END)
    time.sleep(1)
    html.send_keys(Keys.END)
    time.sleep(1)
    html.send_keys(Keys.ARROW_UP)
    try:
        wait.until(EC.presence_of_all_elements_located((By.XPATH, "//*[@id='resultPane']/div["+str(c)+"]/span")))
        loadButton=wd.find_element_by_xpath("//*[@id='resultPane']/div["+str(c)+"]/span")
        loadButton.click()
    except TimeoutException or ElementClickInterceptedException:
        break
    time.sleep(1)
    c+=1
wd.close

这是我浏览过的一些类似问题的链接 我尝试添加选项,但它不会工作。其他一些技巧真的让我很困惑,所以我希望有人可以在这里帮助我(我对编码很陌生)

这是我浏览的链接

selenium.WebDriverException: unknown error: session deleted because of page crash from tab crashed

python linux selenium: chrome not reachable

unknown error: session deleted because of page crash from unknown error: cannot determine loading status from tab crashed with ChromeDriver Selenium

只是为了澄清该程序的目标是获取所有配置文件的列表并从中刮取东西,这就是为什么这部分程序首先加载整个页面以获取所有这些链接(afaik 我不能只用它们bsoup 因为 javascript)所以我没有任何解决方法 非常感谢!

【问题讨论】:

您是要打开所有列出的配置文件,还是只打开卡片上可见的内容? 我试图打开网站上的所有配置文件(这就是为什么我指示 selenium 单击加载更多按钮并向下滚动,因为在加载之前找不到链接)希望能回答你的问题跨度> 确实如此。你的情况对于初学者来说有点高级。我会稍微修改一下你的代码并稍后发布。 非常感谢您的帮助:) 如果您能解释一下您所做的更改以便我能够知道我的错误是什么/我可以从中吸取教训,我将不胜感激。 (只是为了澄清我试图获得的输出是每个配置文件的链接列表) 听起来他们一直在加载新内容而不删除旧内容……在 DOM 加载足够多之后,浏览器会崩溃。 (可能是由于 JS 框架过载) 【参考方案1】:

解决方案是从 dom 树中删除元素 就像@pcalkins 上面所说的那样,dom 树似乎“过载”了

【讨论】:

【参考方案2】:

就像我在 cmets 中提到的那样。对于初学者来说,这不是一件容易的事。不过,这段代码应该会给你一个开始。

这里最大的问题是,结果是通过 iframe 加载的,所以你需要先得到它。

看看这段代码,它将获取配置文件的基本信息并将它们作为 json 返回。如果您需要对此进行更多解释,请随时在 cmets 中提问。

import re
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


def get_profile_info(profile_url):
    # gets info of a profile page // Adjust here to get more info
    wd.get(profile_url)
    label_element = WebDriverWait(wd, 5).until(
        EC.presence_of_element_located((By.ID, "labelAddress"))
    )
    label = label_element.find_element_by_tag_name("h1").text

    street = label_element.find_element_by_css_selector(
        "span[itemprop='streetAddress']"
    ).text

    postal_code = label_element.find_element_by_css_selector(
        "span[itemprop='postalCode']"
    ).text

    city = label_element.find_element_by_css_selector(
        "span[itemprop='addressLocality']"
    ).text

    address_region = label_element.find_element_by_css_selector(
        "span[itemprop='addressRegion']"
    ).text

    country = label_element.find_element_by_css_selector(
        "span[itemprop='addressCountry']"
    ).text

    return 
        "label": label,
        "street": street,
        "postal_code": postal_code,
        "city": city,
        "address_region": address_region,
        "country": country,
    


def get_profile_url(label_element):
    # get the url from a result element
    onlick = label_element.get_attribute("onclick")
    # some regex magic
    return re.search(r"(?<=open\(\')(.*?)(?=\')", onlick).group()


def load_more_results():
    # load more results if needed // use only on the search page!
    button_wrapper = wd.find_element_by_class_name("loadNextBtn")
    button_wrapper.find_element_by_tag_name("span").click()


#### Script starts here ####

# Set some Selenium Options
options = webdriver.ChromeOptions()
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")

# Webdriver
wd = webdriver.Chrome(options=options)
# Load URL
wd.get("https://www.techpilot.de/zulieferer-suchen?laserschneiden")


# lets first wait for the timeframe
iframe = WebDriverWait(wd, 5).until(
    EC.frame_to_be_available_and_switch_to_it("efficientSearchIframe")
)

# the result parent
result_pane = WebDriverWait(wd, 5).until(
    EC.presence_of_element_located((By.ID, "resultPane"))
)


result_elements = wd.find_elements_by_class_name("fancyCompLabel")

# lets first collect all the links visible
href_list = []
for element in result_elements:
    url = get_profile_url(element)
    href_list.append(url)

# lets collect all the data now
result = []
for href in href_list:
    result.append(get_profile_info(href))

wd.close

# lets see what we've got
print(result)

【讨论】:

嘿,所以我现在查看了您的代码。 “def get_profile_info(profile_url)” 并不是真正需要的,因为我的其余代码工作得很好。我能够使用您的代码获取配置文件链接,但我无法运行 load_more_results 因为它无法找到加载下一步按钮。 你在等待iframe后使用了load_more_results函数吗? 是的,我注意到了 好的,你也可以简单地执行加载新内容的javascript:wd.execute_script("loadFollowing();"); 嘿,这是我目前的进展:执行负载跟踪脚本的工作比我做的要顺畅得多。问题是当加载太多配置文件时我仍然会出现页面崩溃。 (似乎 dom 树变得太大)我试图从 dom 树中删除已经添加到列表中的元素:)

以上是关于由于未知错误导致页面崩溃,Python Selenium 会话被删除:无法从选项卡崩溃中确定加载状态的主要内容,如果未能解决你的问题,请参考以下文章

执行自动化脚本时出现“org.openqa.selenium.WebDriverException:未知错误:由于页面崩溃而删除会话”错误

如何解决sprintf参数类型错误导致程序崩溃

自动释放池导致 RubyCocoa 应用程序崩溃

Python:未知的 Jinja 错误导致脚本无法运行

由于未定义的行为或编译器错误导致 C++ 代码崩溃?

Python如何修复由于睡眠功能而导致的Tkinter窗口崩溃