无法多次使用PyQt5进行网页抓取

时间:2018-10-22 01:38:48

标签: python python-3.x web-scraping pyqt pyqt5

我正在尝试使用PyQT5 QWebEngineView进行网页抓取。这是我从StackOverflow的另一个响应中获得的代码:

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

def render(url):
    class Render(QWebEngineView):
        def __init__(self, t_url):
            self.html = None
            self.app = QApplication(sys.argv)
            QWebEngineView.__init__(self)
            self.loadFinished.connect(self._loadfinished)
            self.load(QUrl(t_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('http://quotes.toscrape.com/random'))

它按预期工作。但是,如果我在上面添加第二行,它显示为:

print(render('http://quotes.toscrape.com/random'))
print(render('http://quotes.toscrape.com/tableful/'))

正确打印出第一个渲染后,出现错误“处理以退出代码-1073741819(0xC0000005)完成”。

我将错误范围缩小到self.load(QUrl(t_url))

1 个答案:

答案 0 :(得分:1)

您要多次初始化QApplication。全局仅应存在一次实例。如果您需要获取当前实例并且没有该实例的句柄,则可以使用QApplication.instance()QApplication.quit()的意思是在sys.exit之前被调用,实际上,您几乎切勿在没有另一个的情况下使用一个。

简而言之,您要告诉Qt您正在退出该应用程序,然后尝试运行更多Qt代码。这很简单,但是...

解决方案

您可以做三件事之一:

将应用程序存储在全局变量中,然后从那里引用它:

APP = QApplication(sys.argv)
# ... Many lines ellipsed

class SomeClass(QWidget):
    def some_method(self):
        APP.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers | QEventLoop.WaitForMoreEvents)

app作为该类的句柄。

def render(app, url):
    ...

创建一个全局实例,并使用QApplication.instance()

APP = QApplication(sys.argv)
# ... Many lines ellipsed

class SomeClass(QWidget):
    def some_method(self):
        app = QApplication.instance()
        app.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers | QEventLoop.WaitForMoreEvents)

做最适合您的事情。