如何获取网页及其框架的 html dom

How to get the html dom of a webpage and its frames

我想在js执行后得到一个网站的DOM。 我还想获取网站中 iframe 的所有内容,类似于我在 Google Chrome 的检查元素功能中所拥有的内容。

这是我的代码:

import sys
from PyQt4 import QtGui, QtCore, QtWebKit

class Sp():
  def save(self):
    print ("call")
    data = self.webView.page().currentFrame().documentElement().toInnerXml()
    print(data.encode('utf-8'))
    print ('finished')
  def main(self):
    self.webView = QtWebKit.QWebView()
    self.webView.load(QtCore.QUrl("http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe_scrolling"))
    QtCore.QObject.connect(self.webView,QtCore.SIGNAL("loadFinished(bool)"),self.save)

app = QtGui.QApplication(sys.argv)
s = Sp()
s.main()
sys.exit(app.exec_())

这给了我网站的 html,但不是 iframe 内的 html。有什么方法可以获取 iframe 的 HTML。

一般来说这是一个很难解决的问题。

主要难点在于无法提前知道每个页面有多少帧。除此之外,每个子帧可能有自己的一组帧,其数量也是未知的。理论上,可以有无限多的嵌套框架,页面永远加载不完(这对于有很多广告的网站来说似乎并不夸张)。

无论如何,下面是您的脚本的一个版本,它在加载每个帧时获取顶级 QWebFrame 对象,并显示您如何访问您感兴趣的一些内容。当您从输出中可以看出,广告插入了很多 "junk" 帧,您需要以某种方式过滤掉这些帧。

import sys, signal
from PyQt4 import QtGui, QtCore, QtWebKit

class Sp():
  def save(self, ok, frame=None):
    if frame is None:
        print ('main-frame')
        frame = self.webView.page().mainFrame()
    else:
        print('child-frame')
    print('URL: %s' % frame.baseUrl().toString())
    print('METADATA: %s' % frame.metaData())
    print('TAG: %s' % frame.documentElement().tagName())
    print()

  def handleFrameCreated(self, frame):
    frame.loadFinished.connect(lambda: self.save(True, frame=frame))

  def main(self):
    self.webView = QtWebKit.QWebView()
    self.webView.page().frameCreated.connect(self.handleFrameCreated)
    self.webView.page().mainFrame().loadFinished.connect(self.save)
    self.webView.load(QtCore.QUrl("http://www.w3schools.com/tags/tryit.asp?filename=tryhtml_iframe_scrolling"))

signal.signal(signal.SIGINT, signal.SIG_DFL)
print('Press Crtl+C to quit\n')
app = QtGui.QApplication(sys.argv)
s = Sp()
s.main()
sys.exit(app.exec_())

NB:重要的是您连接到主机loadFinished信号而不是网络-看法。如果连接到后者,如果页面包含多个框架,它将被多次调用。