如何抓取JavaScript呈现的HTML

时间:2018-11-11 13:39:12

标签: python selenium-webdriver web-scraping

我需要编写一个自动抓取工具,该工具可以处理由JavaScript渲染的网站(例如YouTube),或者只是在HTML的某个位置使用一些JavaScript来生成某些内容(例如生成版权年份),然后下载其HTML源没有意义,因为它不是最终的代码(用户将看到的代码)。

我将Python与Selenium和WebDriver结合使用,以便可以在给定的网站上执行JavaScript。为此,我的代码是:

def execute_javascript_on_website(self, js_command):
   driver = webdriver.Firefox(firefox_options = self.webdriver_options, executable_path = os.path.dirname(os.path.abspath(__file__)) + '/executables/geckodriver')
   driver.get(self.url)

  try:
     return driver.execute_script(js_command)

  except Exception as exception_message:
     pass

  finally:
     driver.close()

js_command = "return document.documentElement.outerHTML;"处。

通过此代码,我可以获取源代码,但不能获取呈现的代码。我可以做js_command = "return document;"(就像在控制台中所做的那样),但是我会得到<selenium.webdriver.firefox.webelement.FirefoxWebElement (session="5a784804-f623-3041-9840-03f13ce83f53", element="585b43a1-f3b2-1e4a-b348-4ddaf2944550")>具有HTML的对象,但是不可能从中删除它。

有人知道如何使用Selenium来获取JavaScript呈现的HTML(最好是字符串形式)的方法吗?还是其他可以做到的技术?

PS 。:我也尝试了WebDriver等待,但这没有帮助,我仍然获得了HTML和未重编JavaScript。

PPS:我需要获取带有HTML渲染的完整HTML代码(整个html标签)(例如,在浏览器检查器中进行检查时)。或者至少要获取已经呈现JavaScript的网站的DOM。

2 个答案:

答案 0 :(得分:0)

driver.execute_script("return document.getElementsByTagName('html')[0].innerHTML")

答案 1 :(得分:0)

我已经研究过了,我不得不承认@Rumpelstiltskin Koriat的答案中的JavaScript是有效的。当前年份存在于返回的HTML字符串中,并放置在script标记之后(如@pguardiario所述,它必须在此处,因为它只是HTML标记)。我还发现,在这种情况下,通过脚本标签提供简单的JavaScript代码,甚至不需要WebriverWait即可获取具有渲染JavaScript代码的HTML字符串。显然,我已经设法忽略了我急切想要的JavaScript字符串渲染。

我还发现(如@Corey Goldberg所建议的那样),Selenium方法也很好用,同时看起来比纯JavaScript行driver.find_element_by_tag_name('html').get_attribute('innerHTML')更好。然后,它返回一个字符串,而不返回任何webelement。

另一方面,当需要刮除Angular支持的网站的整个HTML时,有必要在理想情况下(至少在YouTube网站中)找到带有id="content"的标签(然后将此位置包括在代码稍后使用的所有XPath的开头-模拟我们有一个完整的HTML)或其中一个标记。这里也不需要WebriverWait。 但是,当仅定位HTML标记或 yt-app 标记或带有id="content"的标记之外的任何其他标记时,则会返回带有未渲染JavaScript的HTML。 Angular生成的网站中的HTML与Agular自己的标签(浏览器显然会忽略)混合在一起。