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

时间:2014-12-09 22:29:32

标签: 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文档而不是原始的源文档来解析?

2 个答案:

答案 0 :(得分:1)

我看到的唯一方法是实际运行Web引擎...

使用QtWebKit QWebFrame,您可以使用setHtmltoHtml将返回由WebKit调整的源代码...

显然这是一个很大的依赖,但只需安装PySide就可以获得所需的一切。


所以事实证明这比我想象的要糟糕得多,至少需要将Qt与其他代码隔离开来。使用setHtml似乎不允许您立即使用toHtml;必须发生一些异步加载...

寻找一些更简单的WebKit绑定可能会更有意义。

因此,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)

答案 1 :(得分:1)

使用Selenium。 https://selenium-python.readthedocs.org

from selenium import webdriver
browser = webdriver.Chrome()
browser.get('http://example.com')
html_source = browser.page_source

您可以使用lxml解析html_source(Chrome浏览器源代码)。