簡體   English   中英

如何從JavaScript渲染的網頁下載?

[英]How to download from JavaScript rendered webpage?

如何從 JavaScript 呈現的網頁上的鏈接下載? Python 是首選語言。

到目前為止,我已經嘗試在無頭服務器上使用Python 綁定 Selenium 這種方法非常慢,充滿錯誤,並且無法可靠地確定下載進度或成功。 此外,無頭服務器會干擾我的剪貼板(這是一個問題)。 我使用 Firefox,因為它可以配置為下載到默認目錄,但我認為 Chrome 的情況並沒有好多少。

或者,我嘗試過使用 WebKit。

def render(url):
    """Fully render a webpage (JavaScript and all) and return the HTML."""

    import subprocess
    from textwrap import dedent

    script = dedent("""\
    import sys
    from PyQt4.QtCore import QUrl
    from PyQt4.QtGui import QApplication
    from PyQt4.QtWebKit import QWebPage

    class Render(QWebPage):

        def __init__(self, url):
            self.app = QApplication(sys.argv)
            QWebPage.__init__(self)
            self.loadFinished.connect(self._loadFinished)
            self.mainFrame().load(QUrl(url))
            self.app.exec_()

        def _loadFinished(self, result):
            self.frame = self.mainFrame()
            self.app.quit()

    render = Render(sys.argv[1])
    print render.frame.toHtml().toAscii()""").encode()

    process = subprocess.Popen(['python2', '-', url],
                               stderr=subprocess.PIPE,
                               stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE)

    # pipe script into Python's stdin
    return process.communicate(script)[0].decode('latin1')

如果不是因為我需要下載在同一個 session 中,這會很棒。有什么方法可以保留用於呈現頁面的 session 嗎? PyQt4 和 WebKit 只是一堆共享庫。 我不確定如何撕掉他們的內臟,或者這樣的事情是否可能。

現在我只是在做以下事情:

with requests.Session() as session:
    html = session.get(url).text
    link = get_url(html)
    download(link, session=session)

在不深入細節的情況下, get_url(html, url)只是從頁面中提取 JavaScript,取消對 DOM 的所有調用,然后在node中執行它。 真是惡心的東西。。。

我可以安全地呈現網頁並保留 session 的任何方式嗎?

如果 Python 不合適或者 JavaScript 替代方案更優雅,我也願意完全在節點中完成它。 看起來node-dom可能就足夠了? 我不太熟悉它,但我對任何建議都很感興趣。

如果直接命令行選項適合您而不是通過 Python 和/或 Selenium,Google Chrome 可以在無頭模式下運行。 它將在轉儲 DOM 之前完成所有 javascript 渲染。

/usr/local/bin/google-chrome \
  --headless \
  --virtual-time-budget=10000 \
  --timeout=10000 \
  --run-all-compositor-stages-before-draw \
  --user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36" \
  --disable-gpu \
  --dump-dom "https://example.com/index.html" > rendered.html

PyQt5 in Python 2 或 3 在這種情況下可以解決問題。 請注意,function 過於復雜,無法支持使用 WebKit 的早期版本 PyQt5 以及使用 WebEngine 的更高版本。

import sys


def render(source_html):
    """Return rendered HTML."""
    try:
        from PyQt5.QtCore import QEventLoop
        from PyQt5.QtWebEngineWidgets import QWebEngineView
        from PyQt5.QtWidgets import QApplication

        class Render(QWebEngineView):
            """Render HTML with PyQt5 WebEngine."""

            def __init__(self, html):
                self.html = None
                self.app = QApplication(sys.argv)
                QWebEngineView.__init__(self)
                self.loadFinished.connect(self._loadFinished)
                self.setHtml(html)
                while self.html is None:
                    self.app.processEvents(
                        QEventLoop.ExcludeUserInputEvents |
                        QEventLoop.ExcludeSocketNotifiers |
                        QEventLoop.WaitForMoreEvents)
                self.app.quit()

            def _callable(self, data):
                self.html = data

            def _loadFinished(self, result):
                self.page().toHtml(self._callable)
    except ImportError:
        from PyQt5.QtWebKitWidgets import QWebPage
        from PyQt5.QtWidgets import QApplication

        class Render(QWebPage):
            """Render HTML with PyQt5 WebKit."""

            def __init__(self, html):
                self.html = None
                self.app = QApplication(sys.argv)
                QWebPage.__init__(self)
                self.loadFinished.connect(self._loadFinished)
                self.mainFrame().setHtml(html)
                self.app.exec_()

            def _loadFinished(self, result):
                self.html = self.mainFrame().toHtml()
                self.app.quit()

    return Render(source_html).html

或 Python 中的 PyQt4 2.

import sys
from PyQt4.QtGui import QApplication
from PyQt4.QtWebKit import QWebPage


class Render(QWebPage):

    """Fully render HTML, JavaScript and all."""

    def __init__(self, html):
        self.app = QApplication(sys.argv)
        QWebPage.__init__(self)
        self.loadFinished.connect(self._loadFinished)
        self.mainFrame().setHtml(html)
        self.app.exec_()

    def _loadFinished(self, result):
        self.frame = self.mainFrame()
        self.app.quit()

render = Render(html)
result = str(render.frame.toHtml().toAscii())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM