2016-06-10 17 views
6

Jak mogę "renderować" HTML za pomocą PyQt5 v5,6 QWebEngineView?Jak "renderować" HTML za pomocą QWebEngineView PyQt5A

Wykonałem wcześniej zadanie z QWebPage PyQt5 v5.4.1, ale było to suggested, aby wypróbować nowszy QWebEngineView.

Oto że realizacja (na ogół działa zgodnie z oczekiwaniami, ale ma tendencję do powieszenia na czas nieokreślony dla niektórych miejscach i sytuacjach)

def render(source_html): 
    """Fully render HTML, JavaScript and all.""" 

    import sys 
    from PyQt5.QtWidgets import QApplication 
    from PyQt5.QtWebKitWidgets import QWebPage 

    class Render(QWebPage): 
     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 

import requests 
sample_html = requests.get(dummy_url).text 
print(render(sample_html)) 

Poniżej jest moja próba korzystania QWebEngineView. Po pierwsze, instalacja i konfiguracja PyQt5 v5.6 na Ubuntu:

# install PyQt5 v5.6 wheel from PyPI 
pip3 install --user pyqt5 

# link missing resources 
ln -s ../resources/icudtl.dat ../resources/qtwebengine_resources.pak ../resources/qtwebengine_resources_100p.pak ../resources/qtwebengine_resources_200p.pak ../translations/qtwebengine_locales ~/.local/lib/python3.5/site-packages/PyQt5/Qt/libexec/ 

Teraz dla Pythona ... następujące wyniki w winy segmentacji:

def render(source_html): 
    """Fully render HTML, JavaScript and all.""" 

    import sys 
    from PyQt5.QtWidgets import QApplication 
    from PyQt5.QtWebEngineWidgets import QWebEngineView 

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

     def _loadFinished(self, result): 
      # what's going on here? how can I get the HTML from toHtml? 
      self.page().toHtml(self.callable) 
      self.app.quit() 

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

    return Render(source_html).html 

import requests 
sample_html = requests.get(dummy_url).text 
print(render(sample_html)) 

Problem wydaje się leżeć w wywołaniu asynchroniczny toHtml(). Wygląda na to, że powinno być dość proste, ale nie mam pojęcia, co z tym zrobić. Widzę, że było to discussed w kontekście C++, ale nie jestem pewien, jak przetłumaczyć to na Python. Jak mogę uzyskać kod HTML?

Odpowiedz

7

Sporo dyskusji na ten temat została wykonana w wątku: https://riverbankcomputing.com/pipermail/pyqt/2015-January/035324.html

Nowy interfejs QWebEngine uwzględnia faktu, że pod spodem silnika Chromium jest asynchroniczne. W związku z tym musimy zmienić asynchroniczny interfejs API w synchroniczny.

Oto jak to wygląda:

def render(source_html): 
    """Fully render HTML, JavaScript and all.""" 

    import sys 
    from PyQt5.QtCore import QEventLoop 
    from PyQt5.QtWidgets import QApplication 
    from PyQt5.QtWebEngineWidgets import QWebEngineView 

    class Render(QWebEngineView): 
     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) 

    return Render(source_html).html 

import requests 
sample_html = requests.get(dummy_url).text 
print(render(sample_html)) 
4

Jak podkreślił Qt5.4 opiera się na połączeniach asynchronicznych. Nie trzeba używać pętli (jak widać w odpowiedzi), ponieważ jedynym błędem było wywołanie quit przed zakończeniem połączenia toHtml.

def render(source_html): 
    """Fully render HTML, JavaScript and all.""" 

    import sys 
    from PyQt5.QtWidgets import QApplication 
    from PyQt5.QtWebEngineWidgets import QWebEngineView 

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

     def _loadFinished(self, result): 
      # This is an async call, you need to wait for this 
      # to be called before closing the app 
      self.page().toHtml(self.callable) 

     def callable(self, data): 
      self.html = data 
      # Data has been stored, it's safe to quit the app 
      self.app.quit() 

    return Render(source_html).html 

import requests 
sample_html = requests.get(dummy_url).text 
print(render(sample_html)) 
1

Odpowiedź przez sześć & Veehmot jest wielki, ale okazało się, że dla moich celów to nie było wystarczające, ponieważ nie rozszerzać elementy rozwijanej strony, chciałem zeskrobać. Niewielka modyfikacja to:

def render(url): 
    """Fully render HTML, JavaScript and all.""" 

    import sys 
    from PyQt5.QtCore import QEventLoop,QUrl 
    from PyQt5.QtWidgets import QApplication 
    from PyQt5.QtWebEngineWidgets import QWebEngineView 

    class Render(QWebEngineView): 
     def __init__(self, url): 
      self.html = None 
      self.app = QApplication(sys.argv) 
      QWebEngineView.__init__(self) 
      self.loadFinished.connect(self._loadFinished) 
      self.load(QUrl(url)) 
      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) 

    return Render(url).html 


print(render(dummy_url)) 
Powiązane problemy