2016-10-04 66 views
2

我想检索网页的所有可见内容。比如说,例如this网页。我用硒远程使用无头Firefox浏览器。使用硒和BeautifulSoup获取页面的可见内容

脚本我使用看起来像这样

driver = webdriver.Remote('http://0.0.0.0:xxxx/wd/hub', desired_capabilities) 
driver.get(url) 
dom = BeautifulSoup(driver.page_source, parser) 

f = dom.find('iframe', id='dsq-app1') 
driver.switch_to_frame('dsq-app1') 
s = driver.page_source 
f.replace_with(BeautifulSoup(s, 'html.parser')) 

with open('out.html', 'w') as fe: 
    fe.write(dom.encode('utf-8')) 

这应该加载网页,解析DOM,然后用ID dsq-app1取代的iframe与它的可见内容。如果我通过我的python命令行逐一执行这些命令,它按预期工作。然后我可以看到所有可见内容的段落。相反,我一次执行所有这些命令,无论是通过执行脚本还是将所有此代码片段粘贴到解释器中,它的行为都有所不同。段落丢失,内容仍然以json格式存在,但这不是我想要的。

任何想法为什么会发生这种情况?可能与replace_with有关?

回答

1

当您的代码尝试访问它们时,dom元素的声音尚未加载。

尝试wait为元素被完全加载,然后替换。

这适用于您在通过命令运行命令时的作用,因为这样您就可以让驱动程序在执行更多命令之前加载所有元素。

0

尝试在检测到所需ID/CSS_SELECTOR/CLASS或LINK后获取页面源。

您可以随时使用Selenium WebDriver的显式等待。

from selenium.webdriver.support.ui import WebDriverWait 
from selenium.webdriver.support import expected_conditions as EC 
from selenium.webdriver.common.by import By 
driver = webdriver.Remote('http://0.0.0.0:xxxx/wd/hub', desired_capabilities) 
driver.get(url) 
f = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,idName) 
# here 10 is time for which script will try to find given id 
# provide the id name 
dom = BeautifulSoup(driver.page_source, parser) 

f = dom.find('iframe', id='dsq-app1') 
driver.switch_to_frame('dsq-app1') 
s = driver.page_source 
f.replace_with(BeautifulSoup(s, 'html.parser')) 

with open('out.html', 'w') as fe: 
    fe.write(dom.encode('utf-8')) 

纠正我,如果这个不行

+0

这是我第一次学尝试,但它不是正常工作,因为该项目在实际上完全加载之前可能会出现。我猜这个等待页面加载的整个主题是错综复杂的,但是我通过检查iframe的readyState来解决它。 – LetsPlayYahtzee

+0

非常好。它可能在未来帮助我。谢谢 –

+0

我提供了我的解决方案,检查波纹管 – LetsPlayYahtzee

1

添加或段的回答我提供什么样的我落得这样做。查找页面或页面部分是否已完全加载的问题是复杂的。我试图使用隐式和显式等待,但我最终收到了半载帧。我的解决方法是检查原始文档的readyState和iframe的readyState。

下面是一个简单的功能

def _check_if_load_complete(driver, timeout=10): 
    elapsed_time = 1 
    while True: 
     if (driver.execute_script('return document.readyState') == 'complete' or 
       elapsed_time == timeout): 
      break 
     else: 
      sleep(0.0001) 
     elapsed_time += 1 

然后我用该功能之后,我改变了司机的重点,在iframe

driver.switch_to_frame('dsq-app1') 
_check_if_load_complete(driver, timeout=10)