&引用;未能解码来自木偶的响应;Python/Firefox无头抓取脚本中的消息
你好,我已经在这里和谷歌上做了很多搜索,还没有找到解决这个问题的方法 情况是: 我有一个Python脚本(2.7),它循环遍历许多URL(例如,想想Amazon页面,抓取评论)。每个页面都有相同的HTML布局,只需抓取不同的信息。我将Selenium与无头浏览器结合使用,因为这些页面具有需要执行的javascript来获取信息 我在本地机器(OSX 10.10)上运行此脚本。Firefox是最新的v59。Selenium版本为3.11.0,使用geckodriver v0.20 这个脚本在本地没有任何问题,它可以运行所有的URL,并在没有问题的情况下刮取页面 现在,当我把脚本放在我的服务器上时,唯一的区别是它是Ubuntu 16.04(32位)。我使用了适当的geckodriver(仍然是v0.20),但其他一切都是一样的(Python 2.7,Selenium 3.11)。它似乎随机使无头浏览器崩溃,然后所有的&引用;未能解码来自木偶的响应;Python/Firefox无头抓取脚本中的消息,python,selenium,firefox,web-scraping,geckodriver,Python,Selenium,Firefox,Web Scraping,Geckodriver,你好,我已经在这里和谷歌上做了很多搜索,还没有找到解决这个问题的方法 情况是: 我有一个Python脚本(2.7),它循环遍历许多URL(例如,想想Amazon页面,抓取评论)。每个页面都有相同的HTML布局,只需抓取不同的信息。我将Selenium与无头浏览器结合使用,因为这些页面具有需要执行的javascript来获取信息 我在本地机器(OSX 10.10)上运行此脚本。Firefox是最新的v59。Selenium版本为3.11.0,使用geckodriver v0.20 这个脚本在本地没
browservjt.get('url…')
都不再工作
错误消息显示:
消息:未能解码来自木偶的响应
任何进一步的selenium页面请求都会返回错误:
消息:尝试在不建立连接的情况下运行命令
要显示一些代码: 创建驱动程序时:
options = Options()
options.set_headless(headless=True)
driver = webdriver.Firefox(
firefox_options=options,
executable_path=config.GECKODRIVER
)
driver
作为参数browservebj
传递给脚本函数,然后用于调用特定页面,加载后传递给BeautifulSoup进行解析:
browserObj.get(url)
soup = BeautifulSoup(browserObj.page_source, 'lxml')
错误可能指向正在使浏览器崩溃的BeautifulSoup行 这可能是什么原因造成的,我能做些什么来解决这个问题
编辑:添加指向相同对象的堆栈跟踪:
Traceback (most recent call last):
File "main.py", line 164, in <module>
getLeague
File "/home/ps/dataparsing/XXX/yyy.py", line 48, in BBB
soup = BeautifulSoup(browserObj.page_source, 'lxml')
File "/home/ps/AAA/projenv/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 670, in page_source
return self.execute(Command.GET_PAGE_SOURCE)['value']
File "/home/ps/AAA/projenv/local/lib/python2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 312, in execute
self.error_handler.check_response(response)
File "/home/ps/AAA/projenv/local/lib/python2.7/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
raise exception_class(message, screen, stacktrace)
WebDriverException: Message: Failed to decode response from marionette
回溯(最近一次呼叫最后一次):
文件“main.py”,第164行,在
getLeague
文件“/home/ps/dataparsing/XXX/yyy.py”,第48行,在BBB中
soup=BeautifulSoup(browservebj.page_来源“lxml”)
文件“/home/ps/AAA/projenv/local/lib/python2.7/site packages/selenium/webdriver/remote/webdriver.py”,第670行,在第页的源代码中
返回self.execute(Command.GET_PAGE_SOURCE)['value']
文件“/home/ps/AAA/projenv/local/lib/python2.7/site packages/selenium/webdriver/remote/webdriver.py”,第312行,在execute中
self.error\u handler.check\u响应(响应)
文件“/home/ps/AAA/projenv/local/lib/python2.7/site packages/selenium/webdriver/remote/errorhandler.py”,第242行,在check_响应中
引发异常类(消息、屏幕、堆栈跟踪)
WebDriverException:消息:未能解码来自木偶的响应
注意:此脚本用于处理Chrome。因为服务器是32位服务器,所以我只能使用chromedriver v0.33,它只支持ChromeV60-62。目前Chrome是v65,在DigitalOcean上,我似乎没有一个简单的方法恢复到旧版本——这就是为什么我一直使用Firefox。我仍然不知道为什么会发生这种情况,但我可能已经找到了解决办法。我在一些文档中读到可能存在竞争条件(关于什么,我不确定,因为不应该有两个项目竞争相同的资源) 我更改了抓取代码以执行此操作:
import time
browserObj.get(url)
time.sleep(3)
soup = BeautifulSoup(browserObj.page_source, 'lxml')
没有具体原因说明为什么我选择了3秒,但自从添加此延迟后,我没有收到任何要刮取的URL列表中的消息:未能解码来自木偶的响应
更新日期:2018年10月
六个月后,这仍然是一个问题。Firefox、Geckodriver、Selenium和PyVirtualDisplay都已更新至其最新版本。这个错误不断地自发地重复出现,没有规律:有时有效,有时无效
解决此问题的方法是将服务器上的RAM从1 GB增加到2 GB。自增长以来,没有出现过这种失败 对于在Docker容器中运行selenium webdriver时遇到此问题的任何其他人,请修复
如果OP通过将服务器RAM升级到2Gb来解决物理机器的问题,我想这也会影响物理机器,但这可能是巧合。这背后可能存在的真正问题是DOM尚未加载,而您正在触发下一页的搜索。这就是为什么睡眠(3)
在大多数情况下都能工作的原因。正确的解决方法是使用wait类
这是一个使用Nextcloud的wait函数的示例测试用例。它来自我的docker selenium firefox python图像:
请注意如何围绕任何单击或获取调用调用wait
类。基本上,这可以利用selenium在页面加载时更改HTML
标记的ID这一事实。wait函数检查新ID是否与旧ID不同,如果不同,则DOM已加载
import time
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.keys import Keys
class wait(object):
def __init__(self, browser):
self.browser = browser
def __enter__(self):
self.old_page = self.browser.find_element_by_tag_name('html')
def page_has_loaded(self):
new_page = self.browser.find_element_by_tag_name('html')
return new_page.id != self.old_page.id
def __exit__(self, *_):
start_time = time.time()
while time.time() < start_time + 5:
if self.page_has_loaded():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for page load.')
def test():
try:
opts = Options()
opts.headless = True
assert opts.headless # Operating in headless mode
browser = Firefox(options=opts)
except Exception as e:
print(" -=- FAIL -=-: Browser setup - ", e)
return
# Test title
try:
with wait(browser):
browser.get('https://nextcloud.mydomain.com/index.php/login')
assert 'Nextcloud' in browser.title
except Exception as e:
print(" -=- FAIL -=-: Initial load - ", e)
return
else:
print(" Success: Initial load")
try:
# Enter user
elem = browser.find_element_by_id('user')
elem.send_keys("MYUSER")
# Enter password
elem = browser.find_element_by_id('password')
elem.send_keys("MYPASSWORD")
# Submit form
elem = browser.find_element_by_id('submit')
with wait(browser):
elem.click()
# Check title for success
assert 'Files' in browser.title
except Exception as e:
print(" -=- FAIL -=-: Login - ", e)
return
else:
print(" Success: Login")
print(" Finished.")
print("Testing nextcloud...")
test()
导入时间
从selenium.webdriver导入Firefox
从selenium.webdriver.firefox.options导入选项
从selenium.webdriver.common.keys导入密钥
类等待(对象):
定义初始化(自我,浏览器):
self.browser=浏览器
定义输入(自我):
self.old_page=self.browser.find_element_by_tag_name('html'))
def页面已加载(自):
新建页面=self.browser。通过标签名称(“html”)查找元素
返回新的页面id!=self.old_page.id
定义uuu退出uuu(自我,*uu):
开始时间=time.time()
while time.time()firefox_binary='/home/user/Downloads/old_firefox/firefox/firefox'
Message: failed to decode response from marionette
DEBUG <- 500 Internal Server Error {"value":{"error":"unknown error","message":"Failed to decode response from marionette","stacktrace":...}...}
--memory 1024mb --shm-size 2g
--memory 1024mb