python - 如何将 Chrome 版本的网页提供给 python?

标签 python google-chrome web-scraping lxml

我正在努力让用户轻松地从网页输入数字。我能想象到的最简单的事情就是让他们提供一个 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,您可以使用 setHtmltoHtml将返回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/

相关文章:

python - 如何在让管理员在 Django 中默认工作的同时为我的应用程序创建自定义用户模型?

javascript - iOS 版 Chrome 与 <样式> 高度 : 100vh;&lt;/style&gt;

google-chrome - 强制 Chrome 接受任何 SSL 证书,无论它是由谁签署的?

c# - HttpClient 没有获得完整的网站 html 源代码

python - bs4 在给定标签的所有属性中搜索一个词

Python 2.7 警告 : __init__ not compatible to __new__

python返回值遇到error.help me

python - 如何将文件重命名为文件名中的子字符串?

google-chrome - 谷歌浏览器堆快照保留大小的测量单位是什么?

Python 3 网页转行