[英]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.