web = QWebEngineView() parser = argparse.ArgumentParser() parser.add_argument('X', type=int, help='1st is x') parser.add_argument('Y', type=int, help='2nd is y') parser.add_argument('W', type=int, help='3rd is w') parser.add_argument('H', type=int, help='4th is h') parser.add_argument('U', type=str, help='5th is u') arg = parser.parse_args() left = arg.X top = arg.Y width = arg.W height = arg.H url = arg.U web.setWindowFlags(Qt.FramelessWindowHint) web.setGeometry(left, top, width, height) web.setAttribute(Qt.WA_DeleteOnClose, False) web.setFocusPolicy(Qt.NoFocus) web.setContextMenuPolicy(Qt.NoContextMenu) web.setDisabled(True) web.load(url) web.show() sys.exit(app.exec_()) # # #
class AssistantWidget(QtWidgets.QWidget): msg_signal = Signal(str) hidden = False last_position = QPoint(0, 0) current_answer = 0 answers = [] def __init__(self, parent=None): QtWidgets.QWidget.__init__( self, parent, Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.WindowStaysOnTopHint) self.setAttribute(Qt.WA_TranslucentBackground, True) self.runner = KeyloggerRunner() self.runner.start_running(self.msg_signal) self.msg_signal.connect(self.get_events) self.webview = QWebEngineView() self.webview.setAttribute(Qt.WA_StyledBackground) self.webview.setStyleSheet("border: 1px solid black;") self.webview.setContentsMargins(1, 1, 1, 1) self.search_image = QtGui.QPixmap('dialog-search2.png') self.search_label = QtWidgets.QLabel() self.search_legend = QtWidgets.QLabel(text="¿Qué quieres saber?", parent=self.search_label) self.search_label.setPixmap(self.search_image) self.text_input = QtWidgets.QLineEdit(self.search_label) self.search_label.window().setStyleSheet("QLineEdit { border: none }") self.search_label.move(0, 0) self.search_legend.move(34, 120) self.text_input.move(34, 145) self.clear_button = QtWidgets.QPushButton("x") self.progress = QtWidgets.QLabel() movie = QtGui.QMovie("progress.gif") self.progress.setMovie(movie) movie.start() self.previous_button = QtWidgets.QPushButton() self.previous_button.setIcon(QtGui.QIcon('left.png')) self.next_button = QtWidgets.QPushButton() self.next_button.setIcon(QtGui.QIcon('right.png')) self.logo = QtGui.QPixmap('stacko.png') self.logo_label = QtWidgets.QLabel() self.logo_label.setPixmap(self.logo) self.build_layout() self.clear_button.clicked.connect(self.clear_search) self.text_input.returnPressed.connect(self.find_answers) self.previous_button.clicked.connect(self.show_previous_answer) self.next_button.clicked.connect(self.show_next_answer) self.api = StackOverflowApi() self.answers_runner = BackgroundRunner() self.answers_runner.msg_signal.connect(self.answers_loaded) def build_layout(self): self.parent_layout = QtWidgets.QHBoxLayout() self.parent_layout.addLayout(self.build_left_side()) self.parent_layout.addLayout(self.build_right_side()) self.setLayout(self.parent_layout) def build_left_side(self): layout = QtWidgets.QVBoxLayout() layout.addWidget(self.logo_label) return layout def build_right_side(self): layout = QtWidgets.QVBoxLayout() layout.addWidget(self.search_label) layout.addWidget(self.progress) self.progress.setVisible(False) buttons_layout = QtWidgets.QHBoxLayout() layout.addLayout(buttons_layout) buttons_layout.addWidget(self.clear_button) self.clear_button.setVisible(False) buttons_layout.addWidget(self.previous_button) self.previous_button.setVisible(False) buttons_layout.addWidget(self.next_button) self.next_button.setVisible(False) self.webview.setVisible(False) layout.addWidget(self.webview) return layout @Slot(str) def get_events(self, event): callback = getattr(self, f'event_{event}_callback', self.unknown_event_callback) callback(event=event) @Slot(str) def answers_loaded(self, answers_json): answers = json.loads(answers_json) self.answers = answers print(self.answers) self.current_answer = 0 self.previous_button.setVisible(True) self.previous_button.setEnabled(False) self.next_button.setVisible(True) if len(self.answers) > 1: self.next_button.setEnabled(True) self.clear_button.setVisible(True) self.search_label.setVisible(False) self.progress.setVisible(False) self.webview.setWindowOpacity(80) self.webview.setVisible(True) self.webview.setHtml(self.answers[self.current_answer]['content']) def event_invoke_callback(self, **kwargs): if self.hidden: self.show() self.move(self.last_position.x(), self.last_position.y()) self.hidden = False else: self.last_position = self.pos() self.hide() self.hidden = True def event_quit_callback(self, **kwargs): QCoreApplication.quit() def unknown_event_callback(self, event): print(f'Unknown event {event}') def clear_search(self): self.current_answer = 0 self.answers = [] self.previous_button.setVisible(False) self.next_button.setVisible(False) self.clear_button.setVisible(False) self.text_input.clear() self.search_label.setVisible(True) self.search_label.move(0, 0) self.search_legend.move(34, 120) self.text_input.move(34, 145) self.text_input.setVisible(True) self.webview.setVisible(False) def find_answers(self): self.search_label.setVisible(False) self.progress.setVisible(True) self.answers_runner.stop_jobs() self.answers_runner.start_jobs(self.api.get_answers, args=(self.text_input.text(), )) def mousePressEvent(self, event): self.last_position = event.pos() super().mousePressEvent(event) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: diff = event.pos() - self.last_position newpos = self.pos() + diff self.move(newpos) def show_previous_answer(self): if len(self.answers) > 0 and 0 <= self.current_answer - 1 < len( self.answers): self.current_answer = self.current_answer - 1 self.webview.setHtml(self.answers[self.current_answer]['content']) if self.current_answer == 0: self.previous_button.setEnabled(False) if not self.next_button.isEnabled(): self.next_button.setEnabled(True) def show_next_answer(self): if len(self.answers) > 0 and 0 <= self.current_answer + 1 < len( self.answers): self.current_answer = self.current_answer + 1 self.webview.setHtml(self.answers[self.current_answer]['content']) if self.current_answer == len(self.answers) - 1: self.next_button.setEnabled(False) if not self.previous_button.isEnabled(): self.previous_button.setEnabled(True)
class BrowserDialog(QMainWindow): logMessage = Signal(str) captureData = Signal(dict, dict, dict) newCookie = Signal(str, str) #loadFinished = Signal(bool) #urlChanged = Signal(str) #urlNotFound = Signal(QUrl) def __init__(self, parent=None, caption="", width=600, height=600): super(BrowserDialog, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self.resize(width, height) self.setWindowTitle(caption) self.url = None self.domain = None self.headers = {} self.stopped = False self.cookie = '' self.ready = False central = QWidget() self.setCentralWidget(central) self.mainLayout = QVBoxLayout(central) self.topLayout = QHBoxLayout() self.mainLayout.addLayout(self.topLayout) # Status bar self.statusBar = self.statusBar() self.cookieLabel = QScrollLabel() self.cookieLabel.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) self.statusBar.addWidget(self.cookieLabel) self.cookieLabel.textVisible(False) self.loadingLabel = QLabel() self.statusBar.addPermanentWidget(self.loadingLabel) # Adress bar self.addressBar = QLineEdit() self.addressBar.returnPressed.connect(self.addressChanged) self.topLayout.addWidget(self.addressBar) self.addressBar.setVisible(False) # Create WebView self.webview = QWebEngineView(self) QWebEngineSettings.globalSettings().setAttribute( QWebEngineSettings.PluginsEnabled, True) QWebEngineSettings.globalSettings().setAttribute( QWebEngineSettings.ScreenCaptureEnabled, True) self.webpage = WebPageCustom(self.webview) self.webview.setPage(self.webpage) self.mainLayout.addWidget(self.webview) self.webview.show() # Signals self.webpage.logMessage.connect(self.logMessage) self.webpage.cookieChanged.connect(self.cookieChanged) self.webview.urlChanged.connect(self.urlChanged) self.webpage.loadFinished.connect(self.loadFinished) self.webpage.loadStarted.connect(self.loadStarted) #self.webpage.urlNotFound.connect(self.urlNotFound) #self.browserWebview.loadFinished.connect(self.loadFinished) #self.browserWebview.loadStarted.connect(self.loadStarted) # Button layout self.buttonLayout = QHBoxLayout() self.topLayout.addLayout(self.buttonLayout) # Buttons buttonDismiss = QPushButton(self) buttonDismiss.setText("Close") buttonDismiss.setDefault(True) buttonDismiss.clicked.connect(self.close) self.buttonLayout.addWidget(buttonDismiss) def loadPage(self, url="", headers={}, options={}, foldername=None, filename=None, fileext=None): self.url = url self.headers = headers self.options = options self.strip = self.options.get('access_token', '') self.foldername = foldername self.filename = filename self.fileext = fileext try: targeturl = urllib.parse.urlparse(url) self.domain = targeturl.netloc except: self.domain = None request = QWebEngineHttpRequest(QUrl(self.url)) for key, val in self.headers.items(): key = key.encode('utf-8') val = val.encode('utf-8') request.setHeader(QByteArray(key), QByteArray(val)) self.webview.load(request) self.show() @Slot() def loadStarted(self): self.ready = False self.loadingLabel.setText('Loading...') @Slot() def loadFinished(self, ok): if ok: self.ready = True self.loadingLabel.setText('Loading finished.') else: self.ready = False self.loadingLabel.setText('Loading failed.') @Slot() def urlChanged(self, url): url = url.toString().replace(self.strip, '') self.addressBar.setText(url) @Slot() def addressChanged(self): url = self.addressBar.text() request = QWebEngineHttpRequest(QUrl(url)) self.webview.load(request) # Scrape HTML def activateCaptureButton(self, handler): self.captureData.connect(handler) buttonCapture = QPushButton(self) buttonCapture.setText("Capture") buttonCapture.setDefault(True) buttonCapture.clicked.connect(self.captureDataClicked) self.buttonLayout.addWidget(buttonCapture) self.addressBar.setVisible(True) @Slot() def captureDataClicked(self): # Metadata data = {} data['title'] = self.webpage.title() try: data['url'] = { 'final': self.webpage.url().toString().replace(self.strip, ''), 'requested': self.webpage.requestedUrl().toString().replace(self.strip, '') } # Fetch HTML data['text'] = self.getHtml() # Fetch plain text data['plaintext'] = self.getText() if self.foldername is not None: # Screenshot try: fullfilename = makefilename(data['url']['final'], self.foldername, self.filename, fileext='.png', appendtime=True) data['screenshot'] = self.getScreenShot(fullfilename) except Exception as e: self.logMessage.emit('Error capturing screenshot: ' + str(e)) # HTML file try: fullfilename = makefilename(data['url']['final'], self.foldername, self.filename, self.fileext, appendtime=True) file = open(fullfilename, 'wb') if file is not None: try: file.write(data['text'].encode()) finally: file.close() except Exception as e: self.logMessage.emit('Error saving HTML: ' + str(e)) # PDF try: fullfilename = makefilename(data['url']['final'], self.foldername, self.filename, fileext='.pdf', appendtime=True) self.webpage.printToPdf(fullfilename) data['pdf'] = fullfilename except Exception as e: self.logMessage.emit('Error printing to PDF: ' + str(e)) except Exception as e: data['error'] = str(e) self.logMessage.emit(str(e)) # Options options = self.options options['querytime'] = str(datetime.now()) options['querystatus'] = 'captured' options['querytype'] = 'captured' #options['objectid'] = 'url.final' #options['nodedata'] = None # Headers headers = {} self.captureData.emit(data, options, headers) def getHtml(self): def newHtmlData(html): self.capturedhtml = html self.capturedhtml = None self.webpage.toHtml(newHtmlData) waitstart = QDateTime.currentDateTime() while (self.capturedhtml is None) and (waitstart.msecsTo( QDateTime.currentDateTime()) < 1000): QApplication.processEvents() time.sleep(0.01) return self.capturedhtml def getText(self): def newTextData(txt): self.capturedtext = txt self.capturedtext = None self.webpage.toPlainText(newTextData) waitstart = QDateTime.currentDateTime() while (self.capturedtext is None) and (waitstart.msecsTo( QDateTime.currentDateTime()) < 1000): QApplication.processEvents() time.sleep(0.01) return self.capturedtext # https://stackoverflow.com/questions/55231170/taking-a-screenshot-of-a-web-page-in-pyqt5 #screenshots: https://stackoverrun.com/de/q/12970119 def getScreenShot(self, filename): try: # Resize oldSize = self.webview.size() newSize = self.webpage.contentsSize().toSize() self.webview.settings().setAttribute( QWebEngineSettings.ShowScrollBars, False) self.webview.setAttribute(Qt.WA_DontShowOnScreen, True) self.webview.resize(newSize) #self.webview.repaint() #self.webview.show() # Wait for resize waitstart = QDateTime.currentDateTime() while (waitstart.msecsTo(QDateTime.currentDateTime()) < 500): QApplication.processEvents() time.sleep(0.01) # Capture pixmap = QPixmap(newSize) self.webview.render(pixmap, QPoint(0, 0)) pixmap.save(filename, 'PNG') self.webview.resize(oldSize) self.webview.setAttribute(Qt.WA_DontShowOnScreen, False) self.webview.settings().setAttribute( QWebEngineSettings.ShowScrollBars, True) self.repaint() except Exception as e: self.logMessage.emit(str(e)) return filename # Get cookie from initial domain def activateCookieButton(self, handler): self.newCookie.connect(handler) self.cookieLabel.textVisible(True) buttonCookie = QPushButton(self) buttonCookie.setText("Transfer cookie") buttonCookie.setDefault(True) buttonCookie.clicked.connect(self.transferCookieClicked) self.buttonLayout.addWidget(buttonCookie) self.addressBar.setVisible(True) @Slot() def transferCookieClicked(self): self.newCookie.emit(self.domain, self.cookie) @Slot(str, str) def cookieChanged(self, domain, cookie): if domain == self.domain: self.cookie = cookie self.cookieLabel.setText("Cookie for domain: " + domain + ": " + cookie)
class Py2WebBrowser(QDialog): def __init__(self, settings=None): super(Py2WebBrowser, self).__init__() self.pwb = QWebEngineView() self.pwb.setAttribute(Qt.WA_DeleteOnClose, True) if settings is not None: self.bconf = settings else: self.bconf = BaseConfig() self.raw_cookies = [] self.cookie_list = [] self.req_obj = QWebEngineHttpRequest() profile = QWebEngineProfile("pyweb", self.pwb) profile.setHttpUserAgent(random.choice(self.bconf.USER_AGENT_LIST)) cookie_store = profile.cookieStore() cookie_store.cookieAdded.connect(self._on_cookie) wp = QWebEnginePage(profile, self.pwb) self.pwb.setPage(wp) self._settings() self.pwb.show() def _settings(self): self.pwb.settings().setAttribute(ws.AutoLoadImages, self.bconf.AUTO_LOAD_IMAGES) self.pwb.settings().setAttribute(ws.JavascriptEnabled, self.bconf.JAVASCRIPT_ENABLED) self.pwb.settings().setAttribute(ws.JavascriptCanOpenWindows, self.bconf.JAVASCRIPT_CAN_OPEN_WINDOWS) self.pwb.settings().setAttribute(ws.LocalStorageEnabled, self.bconf.LOCAL_STORAGE_ENABLED) self.pwb.settings().setAttribute(ws.LocalContentCanAccessRemoteUrls, self.bconf.LOCAL_CONTENT_CAN_ACCESS_REMOTE_URLS) self.pwb.settings().setAttribute(ws.LocalContentCanAccessFileUrls, self.bconf.LOCAL_CONTENT_CAN_ACCESS_FILE_URLS) self.pwb.settings().setAttribute(ws.ErrorPageEnabled, self.bconf.ERROR_PAGES_ENABLED) self.pwb.settings().setAttribute(ws.PluginsEnabled, self.bconf.PLUGINS_ENABLED) self.pwb.settings().setAttribute(ws.WebGLEnabled, self.bconf.WEBGL_ENABLED) self.pwb.settings().setAttribute(ws.AllowRunningInsecureContent, self.bconf.ALLOW_RUNNING_INSECURE_CONTENT) self.pwb.settings().setAttribute(ws.AllowGeolocationOnInsecureOrigins, self.bconf.ALLOW_GEOLOCATION_ON_INSECURE_ORIGINS) self.pwb.settings().setAttribute(ws.ShowScrollBars, self.bconf.SHOW_SCROLL_BARS) self.pwb.settings().setAttribute(ws.DnsPrefetchEnabled, self.bconf.DNS_PREFETCH_ENABLED) def _loadFinished(self): self.pwb.page().toHtml(self._page_to_var) self.pwb.page().runJavaScript(self.s) def _page_to_var(self, html): self.page_source = html self._to_json() self._return() def _on_cookie(self, cookie): for i in self.raw_cookies: if i.hasSameIdentifier(cookie): return self.raw_cookies.append(QNetworkCookie(cookie)) def _to_json(self): for i in self.raw_cookies: data = { "name": bytearray(i.name()).decode(), "domain": i.domain(), "value": bytearray(i.value()).decode(), "path": i.path(), "expireData": i.expirationDate().toString(), "secure": i.isSecure(), "httpOnly": i.isHttpOnly() } self.cookie_list.append(data) def _return(self): self.return_ = { "url": str(self.req_obj.url().toString()), "cookies": self.cookie_list, "content": str(self.page_source) } self.accept() def get(self, url: str, script: str = None): self.s = script self.req_obj.setUrl(QUrl().fromUserInput(url)) self.pwb.page().profile().cookieStore().deleteAllCookies() self.pwb.load(self.req_obj) self.pwb.loadFinished.connect(self._loadFinished)