我正在努力让用户轻松地从网页输入数字。我能想象到的最简单的事情就是让他们提供一个 url 和一个与该号码关联的 xpath。然后我的代码可以去抓取数字。 xpath 的概念(对于非编码人员来说)并不为人所知,但使用 Chrome 的 Inspect 和 Developer 工具查找 xpath 是微不足道的。那太好了。
问题是 Chrome 和 Firefox 中的 xpath 并不总能为您提供可在 html 解析器中使用的有效 xpath,如下所述: Why does this xpath fail using lxml in python?
基本上,浏览器会将源代码更改为技术上更正确的形式,然后向用户显示更改后的形式,并将其 xpath 建立在该形式的基础上。
如果有一种自动方式可以让您的代码看到的不是页面源代码,而是 Chrome 的页面源代码呈现,则可以修复此问题。有没有一种有效的、自动的方法来做到这一点?
再一次,更简洁、更准确:我如何向 python 提供 Chrome 生成的更改后的 HTML 文档,而不是原始源文档来解析?
最佳答案
我看到的唯一方法是实际运行网络引擎......
通过 QtWebKit QWebFrame
,您可以使用 setHtml
和 toHtml
将返回WebKit改编的源代码...
显然这是一个很大的依赖项,但只需安装 PySide将为您提供所需的一切。
所以这比我预期的要脏得多,至少是将 Qt 与其他代码隔离所需的部分。使用setHtml
似乎并不能让你立即使用toHtml
;必须发生一些异步加载...
寻找一些更简单的 WebKit 绑定(bind)可能会更有意义。
因此,load_source
既从 URL 下载数据,又返回 WebKit 修改后的 HTML。它用异步事件包装了 Qt 的事件循环,并且是一个阻塞函数。
setUrl
可以替换为setHtml
。
from PySide.QtCore import QObject, QUrl, Slot
from PySide.QtGui import QApplication
from PySide.QtWebKit import QWebPage, QWebSettings
qapp = QApplication([])
def load_source(url):
page = QWebPage()
page.settings().setAttribute(QWebSettings.AutoLoadImages, False)
page.mainFrame().setUrl(QUrl(url))
class State(QObject):
src = None
finished = False
@Slot()
def loaded(self, success=True):
self.finished = True
if self.src is None:
self.src = page.mainFrame().toHtml()
state = State()
# Optional; reacts to DOM ready, which happens before a full load
def js():
page.mainFrame().addToJavaScriptWindowObject('qstate$', state)
page.mainFrame().evaluateJavaScript('''
document.addEventListener('DOMContentLoaded', qstate$.loaded);
''')
page.mainFrame().javaScriptWindowObjectCleared.connect(js)
page.mainFrame().loadFinished.connect(state.loaded)
while not state.finished:
qapp.processEvents()
return state.src
使用链接问题中的示例进行演示。现在它确实有效了...
from lxml import html
url = 'http://www.makospearguns.com/product-p/mcffgb.htm'
xpath = '//*[@id="v65-product-parent"]/tbody/tr[2]/td[2]/table[1]/tbody/tr/td/table/tbody/tr[2]/td[2]/table/tbody/tr[1]/td[1]/div/table/tbody/tr/td/font/div/b/span/text()'
src = load_source(url)
tree = html.fromstring(src)
text = tree.xpath(xpath)
关于python - 如何将 Chrome 版本的网页提供给 python?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27390108/