@eellazy

Почему вылетает поток в QThreads?

Всем привет!
Может быть кто-то сталкивался с проблемой. Стоит последний Python и последняя версия библиотеки Beautiful soup.
Хочу в потоке начать парсить страницы. Поток без Beautiful soup работает на ура. Но как только я подставляю функционал парсинга выскакивает ошибка
QThread: Destroyed while thread is still running

Самое интересное это то, что при запуске я прохожу две итерации в цикле, а дальше вылетает с ошибкой

Класс создания потока
class ParserController:
    def __init__(self, model, view):
        self._model = model
        self._view = view

    def query_add(self, data):
        if self._model.insert_data(data):
            print('Запись добавлена в базу')
        else:
            print('Запись НЕ добавлена в базу')

    def start_parse_autovia(self):
        self.thread_1 = QtCore.QThread()
        self.autovia_thread = ParseAutovia()
        self.autovia_thread.moveToThread(self.thread_1)
        self.thread_1.started.connect(self.autovia_thread.run)
        self.autovia_thread.query.connect(self.query_add)
        self.autovia_thread.finished.connect(self.thread_1.quit)
        self.thread_1.start()


Класс самого парсера
class ParseAutovia(QtCore.QObject):
    finished = QtCore.pyqtSignal()
    query = QtCore.pyqtSignal(dict)

    START_PAGE = 'https://www.autovia.sk/osobne-auta'
    PAGINATION_PAGE = 'https://www.autovia.sk/osobne-auta/?p[page]='

    def get_data(self, html):
        # Get title
        try:
            title = html.find('h1').text.strip()
        except:
            title = ''

        # Get phone
        try:
            phone = html.find('div', class_='resp-buttons').find_all('a')[0]['href']
        except:
            phone = ''

        # Get name
        try:
            name = html.find('div', class_='resp-contact-top').find('span', class_='resp-subject').text.strip()
        except:
            name = ''

        # Get location
        try:
            location = html.find('div', class_='resp-contact-bottom').find('div', class_='resp-location').find('span').text.strip()
        except:
            location = ''

        # Get date
        try:
            date = html.find('div', class_='resp-meta').find_all('div', class_='col-6')[0].text.strip()
            date = date.replace('Aktualizované: ', '')
        except:
            date = ''

        # Get login
        try:  # Логин продавца
            login = html.find('div', class_='resp-contact-top').find('a', class_='resp-subject').text.strip()
        except:
            login = ''

        # Get login link
        try:
            login_link = html.find('div', class_='resp-contact-top').find('a', class_='resp-subject')['href']
        except:
            login_link = ''

        # Get page link
        try:
            page_link = html.find('meta', attrs={'property': 'og:url'})['content']
        except:
            page_link = ''

        data = {
            'title': title,
            'phone': phone,
            'name': name,
            'location': location,
            'date': date,
            'login': login,
            'login_link': login_link,
            'page_link': page_link
        }

        return data

    def get_html(self, url):
        r = requests.get(url)
        soup = BeautifulSoup(r.text, 'lxml')
        return soup

    def get_pagination_count(self):
        soup = self.get_html(self.START_PAGE)
        count = soup.find('div', class_='resp-pager').find('label', class_='resp-after').text.strip()
        count = int(count.replace('z', '').replace(' ', ''))
        return count

    def get_pagination_links(self, pagination):
        url = self.PAGINATION_PAGE + str(pagination)
        soup = self.get_html(url)

        links = []
        items = soup.find('section', class_='resp-search-results').find_all('div', class_='resp-item')

        for item in items:
            link = item.find('h2').find('a').get('href')
            links.append(link)

        return links

    def run(self):
        pagination_count = self.get_pagination_count()
        pagination = 1

        while pagination <= pagination_count:
            pagination_links = self.get_pagination_links(pagination)

            for url in pagination_links:
                html = self.get_html(url)
                data = self.get_data(html)

                self.query.emit(data)
                print(data['phone'])

            pagination += 1

        self.finished.emit()


Если запустить это в потоке - без проблем отработает
def run(self):
        for i in range(100):
            print(i)
            i += 1
            time.sleep(2)


Прилагаю точку входа в программу
import sys

from PyQt5 import QtWidgets
from model.ParserModel import ParserModel
from controller.ParserController import ParserController


class AppParser(QtWidgets.QApplication):
    def __init__(self, sys_args):
        super(AppParser, self).__init__(sys_args)
        self._model = ParserModel()
        self._controller = ParserController(self._model)

def main():
    app = AppParser(sys.argv)
    sys.exit(app.exec())

if __name__ == '__main__':
    main()
  • Вопрос задан
  • 345 просмотров
Пригласить эксперта
Ответы на вопрос 1
HemulGM
@HemulGM Куратор тега Python
Delphi Developer, сис. админ
Ты программу-то держи запущенной, иначе после запуска потоков она у тебя отправится в завершение и вот ты получаешь ошибку
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы