2016-06-10 34 views
6

PyQt5 v5.6 QWebEngineView ile HTML'yi nasıl "işleyebilirim"?PyQt5'in QWebEngineView'iyle HTML nasıl oluşturulur

Daha önce bu görevi PyQt5 v5.4.1 QWebPage ile gerçekleştirdim, ancak daha yeni QWebEngineView'i denemek için suggested oldu.

İşte o uygulama var (genellikle beklendiği gibi çalışır, ancak bazı siteler ve durumlar için süresiz asmak için bir eğilimi var): Aşağıda QWebEngineView kullanarak benim girişimi

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)) 

olduğunu. Ubuntu üzerinde Birincisi, kurulum ve PyQt5 v5.6 kurulumu: Python ... parçalama arızası aşağıdaki sonuçlar için Şimdi

# 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/ 

:

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)) 

sorun asenkron çağrısına yalan görünüyor toHtml(). Oldukça basit olması gerekiyormuş gibi görünüyor, ama onunla ne yapacağım konusunda bir kayıp yapıyorum. C++ bağlamında discussed olduğunu görüyorum, fakat bunu Python'a nasıl çevireceğimi bilmiyorum. HTML'yi nasıl alabilirim? konu üzerine tartışma

cevap

7

Oldukça biraz aşağıdaki iplik yapıldı: https://riverbankcomputing.com/pipermail/pyqt/2015-January/035324.html

yeni QWebEngine arayüzü yatan Krom motor asenkron olması dikkate alır. Bu nedenle senkronize olmayan bir API'yi senkronize bir ağa dönüştürmek zorundayız.

İşte o nasıl göründüğü:

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

Sizin de belirttiğiniz gibi, Qt5.4 zaman uyumsuz aramalar dayanır. Döngü'nün (cevabınızda görüldüğü gibi) kullanılması gerekli değildir, çünkü tek hata, toHtml çağrı bitirmeden önce quit'u aramaktı.

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

Altı & Veehmot tarafından cevap harika ama bunu ben kazımak istedi sayfanın açılan elemanlarını genişletmek vermedi benim amaç için bu yeterli değildi öğrendim. Küçük bir değişiklik düzeltildi:

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))