예제 #1
0
class TestFindText(TimedQApplication):
    '''Test cases for finding text'''
    def setUp(self):
        TimedQApplication.setUp(self, timeout=TIMEOUT)
        self.page = QWebPage()
        QObject.connect(self.page, SIGNAL('loadFinished(bool)'),
                        self.load_finished)
        self.called = False

    def tearDown(self):
        #Release resources
        del self.page
        self.called = False
        TimedQApplication.tearDown(self)

    def testFindSelectText(self):
        url = QUrl.fromLocalFile(adjust_filename('fox.html', __file__))
        self.page.mainFrame().load(url)
        self.app.exec_()
        self.assert_(self.called)

    def load_finished(self, ok):
        #Callback to check if load was successful
        if ok:
            self.called = True
            self.assert_(self.page.findText('fox'))
            self.assertEqual(self.page.selectedText(), 'fox')
        self.app.quit()
class ImageRenderer(QObject):

    def __init__(self, url, image_path):
        QObject.__init__(self)
        self.url = QUrl(url)
        self.image_path = image_path
        self.webpage = QWebPage(self)
        self.webpage.loadFinished.connect(self.render)
        self.webpage.mainFrame().load(self.url)

    def render(self, ok):
        if ok:
            print('Loaded {0}'.format(self.url.toString()))
            self.webpage.setViewportSize(
                self.webpage.mainFrame().contentsSize())
            image = QImage(self.webpage.viewportSize(),
                           QImage.Format_ARGB32)
            painter = QPainter(image)

            self.webpage.mainFrame().render(painter)
            painter.end()

            if image.save(self.image_path):
                print('Saved image to {0}'.format(self.image_path))
            else:
                print('Could not save to {0}'.format(self.image_path))
        else:
            print('Could not load {0.toString()}'.format(self.url))

        QApplication.instance().quit()
예제 #3
0
class TestFindText(TimedQApplication):
    '''Test cases for finding text'''

    def setUp(self):
        TimedQApplication.setUp(self, timeout=TIMEOUT)
        self.page = QWebPage()
        QObject.connect(self.page, SIGNAL('loadFinished(bool)'),
                        self.load_finished)
        self.called = False

    def tearDown(self):
        #Release resources
        del self.page
        self.called = False
        TimedQApplication.tearDown(self)

    def testFindSelectText(self):
        url = QUrl.fromLocalFile(adjust_filename('fox.html', __file__))
        self.page.mainFrame().load(url)
        self.app.exec_()
        self.assert_(self.called)

    def load_finished(self, ok):
        #Callback to check if load was successful
        if ok:
            self.called = True
            self.assert_(self.page.findText('fox'))
            self.assertEqual(self.page.selectedText(), 'fox')
        self.app.quit()
예제 #4
0
class ImageRenderer(QObject):
    def __init__(self, url, image_path):
        QObject.__init__(self)
        self.url = QUrl(url)
        self.image_path = image_path
        self.webpage = QWebPage(self)
        self.webpage.loadFinished.connect(self.render)
        self.webpage.mainFrame().load(self.url)

    def render(self, ok):
        if ok:
            print('Loaded {0}'.format(self.url.toString()))
            self.webpage.setViewportSize(
                self.webpage.mainFrame().contentsSize())
            image = QImage(self.webpage.viewportSize(), QImage.Format_ARGB32)
            painter = QPainter(image)

            self.webpage.mainFrame().render(painter)
            painter.end()

            if image.save(self.image_path):
                print('Saved image to {0}'.format(self.image_path))
            else:
                print('Could not save to {0}'.format(self.image_path))
        else:
            print('Could not load {0.toString()}'.format(self.url))

        QApplication.instance().quit()
예제 #5
0
class WebThumbnailer(QObject):
    finished = Signal(bool)

    def __init__(self, window_width, window_height):
        super(WebThumbnailer, self).__init__()
        self.ok = None
        self.page = QWebPage(self)
        self.page.mainFrame().setScrollBarPolicy(
                Qt.Horizontal, Qt.ScrollBarAlwaysOff)
        self.page.mainFrame().setScrollBarPolicy(
                Qt.Vertical, Qt.ScrollBarAlwaysOff)
        self.page.loadStarted.connect(self.on_page_started)
        self.page.loadFinished.connect(self.on_page_finished)
        self.page.networkAccessManager().finished.connect(
                self.on_network_finished)
        self.page.setViewportSize(QSize(window_width, window_height))

    def on_page_started(self):
        logging.debug('on_page_started')
        self.ok = None

    def on_page_finished(self, ok):
        logging.debug('on_page_finished: ok=%s', ok)
        self.ok = ok
        self.finished.emit(ok)

    def on_network_finished(self, reply):
        logging.debug('on_network_finished: %s', reply.url().toEncoded())

    def load(self, url):
        self.page.mainFrame().load(url)

    def save(self, out, width=None, height=None):
        image = self.render()
        scaled = self.scale(image, width, height)
        scaled.save(out)
        logging.debug('imagesize: %s', scaled.size())

    def render(self):
        image = QImage(self.page.viewportSize(), QImage.Format_RGB32)
        painter = QPainter(image)
        self.page.mainFrame().render(painter)
        painter.end()
        return image

    def scale(self, image, width=None, height=None):
        if width is None and height is None:
            scaled = image
        elif width is None:
            scaled = image.scaledToHeight(height, Qt.SmoothTransformation)
        elif height is None:
            scaled = image.scaledToWidth(width, Qt.SmoothTransformation)
        else:
            scaled = image.scaled(width, height,
                    Qt.KeepAspectRatioByExpanding,
                    Qt.SmoothTransformation)
            scaled = scaled.copy(0, 0, width, height)
        return scaled
예제 #6
0
class InvoiceForm(QDialog, Ui_InvoiceDialog):

    def __init__(self, parent=None):
        super(InvoiceForm, self).__init__(parent)
        self.setupUi(self)
        self.progressBar.setHidden(True)

        self.invoice = Invoice(self)
        self.tableView.setModel(self.invoice)
        self.tableView.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.tableView.setAlternatingRowColors(True)
        self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.updateButton.clicked.connect(self.update_invoices)
        self.tableView.selectionModel().selectionChanged.connect(self.invoice_selected)

        self.webpage = QWebPage()
        self.webpage.loadFinished.connect(self.save_invoice)
        self.webpage.networkAccessManager().sslErrors.connect(self.allow_connection)

        self.network_access_manager = QNetworkAccessManager()
        self.network_access_manager.finished.connect(self.fetched_invoices)
        self.network_access_manager.sslErrors.connect(self.allow_connection)

    def invoice_selected(self, new, old):
        try:
            row = self.invoice.invoices[new.indexes()[0].row()]
        except IndexError:
            return
        if row[1].startswith('Invoice'):
            self.invoice_filename = os.path.expanduser('~/.blusage/%s.png' % row[1].lower())
            if os.path.exists(self.invoice_filename):
                self.load_invoice()
            else:
                usage = self.parentWidget().usage_model
                url = '%s%s' % (usage.user_endpoint[:-5], self.invoice.invoices[new.indexes()[0].row()][0])
                self.webpage.mainFrame().load(QUrl(url))
                self.webpage.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
                self.webpage.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
                self.webpage.setViewportSize(QSize(800, 600))
                self.enable_ui(False)
        else:
            self.invoiceLabel.setText("""
<center>
    <table>
        <tr>
            <th>Payment #</th>
            <td>{number}</td>
        </tr>
        <tr>
            <th>Date</th>
            <td>{date}</td>
        </tr>
        <tr>
            <th>Credit</th>
            <td>{credit}</td>
        </tr>
        <tr>
            <th>Balance</th>
            <td>{balance}</td>
        </tr>
    </table>
</center>
            """.format(number=row[1][8:], date=row[2], credit=row[3], balance=row[5]))

    def load_invoice(self):
        pixmap = QPixmap(self.invoice_filename)
        self.invoiceLabel.setPixmap(pixmap)

    def update_invoices(self):
        usage = self.parentWidget().usage_model
        url = '%s?%s' % (usage.user_endpoint, self.invoice.post_data)
        request = QNetworkRequest(QUrl(url))
        self.network_access_manager.get(request)
        self.enable_ui(False)

    def enable_ui(self, value=True):
        self.updateButton.setEnabled(value)
        self.progressBar.setHidden(value)
        self.tableView.setEnabled(value)

    def save_invoice(self, ok):
        self.enable_ui()
        if ok:
            frame = self.webpage.mainFrame()
            image = QImage(frame.contentsSize(), QImage.Format_ARGB32_Premultiplied)
            image.fill(Qt.transparent);

            painter = QPainter(image)
            painter.setRenderHint(QPainter.Antialiasing, True);
            painter.setRenderHint(QPainter.TextAntialiasing, True);
            painter.setRenderHint(QPainter.SmoothPixmapTransform, True);
            frame.documentElement().render(painter);
            painter.end();

            image.save(self.invoice_filename)
            self.load_invoice()
        else:
            title = "An error occured"
            message = "Could not load invoice." \
                    + "\nPlease check your internet connection."

            QMessageBox.critical(self, title, message)

    def fetched_invoices(self, reply):
        self.enable_ui()
        if reply.error() == QNetworkReply.NoError:
            html = unicode(reply.readAll())
            self.invoice.parse(html)
            self.invoice.reset()
        else:
            title = "An error occured"
            message = reply.errorString() \
                    + ".\nPlease check your internet connection."

            QMessageBox.critical(self, title, message)
        reply.deleteLater()

    def allow_connection(self, reply):
        reply.ignoreSslErrors()
예제 #7
0
class AvitoAdParser(QObject):
    """Парсер страницы объявления сайта avito.ru"""

    def __init__(self):
        super().__init__()

        self.app = QApplication(sys.argv)

        QNetworkProxyFactory.setUseSystemConfiguration(True)

        self.web_page = QWebPage(self)
        self.web_page.settings().setAttribute(QWebSettings.AutoLoadImages, False)
        self.web_page.loadFinished.connect(self.load_finished)

        # Адрес страницы объявления
        self.url = None

        # Переменная нужна для замера времени выполнения
        self.t = None

        self.phone_img_parser = AvitoPhoneImgParser()

        # Строка с номером телефона
        self.phone = None

        self.proxy_url = None
        self.proxy_type = None
        self.proxy_enabled = None

    # Сигнал вызывается, когда закончен парсинг сотового из объявления
    parse_phone_finished = Signal(str)

    def run(self, url):
        """Функция выполняет парсинг страницы объявления"""

        self.url = url
        self.phone = None

        self.t = time.clock()

        # Загружаем страницу объявления
        self.web_page.mainFrame().load(url)

        logger.debug('Начало выполнения загрузки "{}" {:.3f} секунд'.format(url, time.clock() - self.t))

        # Ждем тут, пока закончится парсинг объявления -- все из-за ассинхронности webpage и моей лени -- хочется
        # просто в цикле запустить обработку и url, но из-за асинхронности с сигналами это не сработает -- какая-то
        # лажа происходит -- падает приложение с ошибкой где-то в QtCore.dll
        loop = QEventLoop()
        self.parse_phone_finished.connect(loop.quit)
        loop.exec_()

        logger.debug('Время выполнения парсера {:.3f} секунд'.format(time.clock() - self.t))
        self.t = None

    def get_phone(self):
        """Функция выполняет поиск картинки с номером телефона, получает его адрес, скачивает, а после
        парсит картинку с номером и записывает в self.phone номер телефона. После парсинга вызывает сигнал
        parse_phone_finished, в котором передается номер телефона.

        """

        # Ищем элемент с картинкой телефона
        el = self.web_page.mainFrame().findFirstElement("img[class='description__phone-img']")

        logger.debug('Поиск изображения телефона {:.3f} секунд'.format(time.clock() - self.t))

        ok = not el.isNull()
        if ok:
            src = el.attribute('src')
            logger.debug('Атрибут src картинки с телефоном: "%s".', src)
            src = src.replace('data:image/png;base64,', '')
            logger.debug('Данные картинки с телефоном: "%s".', src)
            data = base64.b64decode(src)

            # TODO: вызывать исключение, если номер не найден
            # TODO: вызывать исключение, если номер не 11 символов (нормальный номер: 89615750404)
            phone_number = self.phone_img_parser.parse_from_data(data)
            logger.debug('Телефон получен: %s', phone_number)
            logger.debug('Парсинг номера телефона из картинки {:.3f} секунд'.format(time.clock() - self.t))

            self.phone = phone_number
            self.parse_phone_finished.emit(phone_number)

    def find_and_click_element(self):
        """Функция ищет на странице объявления элемент 'Показать телефон' и кликает его, чтобы
        выполнились страшные скрипты и загрузилась картинка с номером телефона

        """

        code = """
        span_phone = $("span[class='description__phone-insert js-phone-show__insert'] span[class='btn__text']")
        span_phone.click()
        """

        logger.debug('Выполняю программный клик по кнопке "Получить телефон"')
        ok = self.web_page.mainFrame().evaluateJavaScript(code)
        if ok is None:
            logger.warn('Выполнение js скрипта неудачно. Code:\n%s', code)
            return

        logger.debug('Время выполнения js скрипта {:.3f} секунд'.format(time.clock() - self.t))
        self.get_phone()

    def load_finished(self, x):
        """Функция вызывается, когда QWebView отсылает сигнал loadFinished"""

        if x and self.phone is None:
            logger.info('Загрузка завершена {:.3f} секунд'.format(time.clock() - self.t))
            self.find_and_click_element()
예제 #8
0
class AvitoAdParser(QObject):
    """Парсер страницы объявления сайта avito.ru"""
    def __init__(self):
        super().__init__()

        self.app = QApplication(sys.argv)

        QNetworkProxyFactory.setUseSystemConfiguration(True)

        self.web_page = QWebPage(self)
        self.web_page.settings().setAttribute(QWebSettings.AutoLoadImages,
                                              False)
        self.web_page.loadFinished.connect(self.load_finished)

        # Адрес страницы объявления
        self.url = None

        # Переменная нужна для замера времени выполнения
        self.t = None

        self.phone_img_parser = AvitoPhoneImgParser()

        # Строка с номером телефона
        self.phone = None

        self.proxy_url = None
        self.proxy_type = None
        self.proxy_enabled = None

    # Сигнал вызывается, когда закончен парсинг сотового из объявления
    parse_phone_finished = Signal(str)

    def run(self, url):
        """Функция выполняет парсинг страницы объявления"""

        self.url = url
        self.phone = None

        self.t = time.clock()

        # Загружаем страницу объявления
        self.web_page.mainFrame().load(url)

        logger.debug('Начало выполнения загрузки "{}" {:.3f} секунд'.format(
            url,
            time.clock() - self.t))

        # Ждем тут, пока закончится парсинг объявления -- все из-за ассинхронности webpage и моей лени -- хочется
        # просто в цикле запустить обработку и url, но из-за асинхронности с сигналами это не сработает -- какая-то
        # лажа происходит -- падает приложение с ошибкой где-то в QtCore.dll
        loop = QEventLoop()
        self.parse_phone_finished.connect(loop.quit)
        loop.exec_()

        logger.debug(
            'Время выполнения парсера {:.3f} секунд'.format(time.clock() -
                                                            self.t))
        self.t = None

    def get_phone(self):
        """Функция выполняет поиск картинки с номером телефона, получает его адрес, скачивает, а после
        парсит картинку с номером и записывает в self.phone номер телефона. После парсинга вызывает сигнал
        parse_phone_finished, в котором передается номер телефона.

        """

        # Ищем элемент с картинкой телефона
        el = self.web_page.mainFrame().findFirstElement(
            "img[class='description__phone-img']")

        logger.debug(
            'Поиск изображения телефона {:.3f} секунд'.format(time.clock() -
                                                              self.t))

        ok = not el.isNull()
        if ok:
            src = el.attribute('src')
            logger.debug('Атрибут src картинки с телефоном: "%s".', src)
            src = src.replace('data:image/png;base64,', '')
            logger.debug('Данные картинки с телефоном: "%s".', src)
            data = base64.b64decode(src)

            # TODO: вызывать исключение, если номер не найден
            # TODO: вызывать исключение, если номер не 11 символов (нормальный номер: 89615750404)
            phone_number = self.phone_img_parser.parse_from_data(data)
            logger.debug('Телефон получен: %s', phone_number)
            logger.debug(
                'Парсинг номера телефона из картинки {:.3f} секунд'.format(
                    time.clock() - self.t))

            self.phone = phone_number
            self.parse_phone_finished.emit(phone_number)

    def find_and_click_element(self):
        """Функция ищет на странице объявления элемент 'Показать телефон' и кликает его, чтобы
        выполнились страшные скрипты и загрузилась картинка с номером телефона

        """

        code = """
        span_phone = $("span[class='description__phone-insert js-phone-show__insert'] span[class='btn__text']")
        span_phone.click()
        """

        logger.debug('Выполняю программный клик по кнопке "Получить телефон"')
        ok = self.web_page.mainFrame().evaluateJavaScript(code)
        if ok is None:
            logger.warn('Выполнение js скрипта неудачно. Code:\n%s', code)
            return

        logger.debug(
            'Время выполнения js скрипта {:.3f} секунд'.format(time.clock() -
                                                               self.t))
        self.get_phone()

    def load_finished(self, x):
        """Функция вызывается, когда QWebView отсылает сигнал loadFinished"""

        if x and self.phone is None:
            logger.info(
                'Загрузка завершена {:.3f} секунд'.format(time.clock() -
                                                          self.t))
            self.find_and_click_element()