Я пытаюсь извлечь данные из URL, когда я запускаю код 1-й раз, когда он работает, но после этого данные отсутствуют?

#python #beautifulsoup #pyqt #pyqt5

Вопрос:

Я пытаюсь получить дату выпуска по URL-адресу, обычные запросы и красивый суп не работают, поэтому попробуйте этот метод, и он работает только 1-й раз, но когда я запускаю его снова, дата выпуска отсутствует. Я не в состоянии понять, в чем проблема.

URL-адрес — https://www.hlj.com/gundam-universe-xxxg-01sr-gundam-sandrock-bans61272
введите описание изображения здесь

введите описание изображения здесь

 from bs4 import BeautifulSoup as bs
import sys
from PyQt5.QtWebEngineWidgets import QWebEnginePage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl

class Page(QWebEnginePage):
    def __init__(self, url):
        self.app = QApplication(sys.argv)
        QWebEnginePage.__init__(self)
        self.html = ''
        self.loadFinished.connect(self._on_load_finished)
        self.load(QUrl(url))
        self.app.exec_()

    def _on_load_finished(self):
        self.html = self.toHtml(self.Callable)
        # print('Load finished')

    def Callable(self, html_str):
        self.html = html_str
        self.app.quit()

    def __del__(self):
        pass

def main():
    page = Page('https://www.hlj.com/gundam-universe-xxxg-01sr-gundam-sandrock-bans61272')
    soup = bs(page.html, 'html.parser')
    js_test = soup.find_all('div', class_='product-date')
    # js_test = js_test()
    js_test = str(js_test[0])
    print(js_test.splitlines())

    del soup
    del page
    del Page._on_load_finished


if __name__ == '__main__': main()
 

Ответ №1:

Проблема вызвана тем, что этот HTML-код создается динамически или асинхронно, поэтому на момент загрузки страницы этот тег еще не существует. Возможное решение состоит в том, чтобы подождать, пока этот тег не будет создан с помощью QTimer и проверки с помощью метода runJavaScript:

 import sys

from bs4 import BeautifulSoup as bs

from PyQt5.QtCore import QCoreApplication, QTimer, QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEnginePage


class Page(QWebEnginePage):
    def __init__(self):
        self.app = QApplication(sys.argv)
        QWebEnginePage.__init__(self)
        self._html = ""
        self._js_script = ""

        self.js_timer = QTimer(interval=100, singleShot=True)

        self.js_timer.timeout.connect(self.handle_timeout)
        self.loadFinished.connect(self._on_load_finished)

    @property
    def html(self):
        return self._html

    @property
    def js_script(self):
        return self._js_script

    def start(self, url):
        self.load(QUrl.fromUserInput(url))
        QCoreApplication.instance().exec_()

    @js_script.setter
    def js_script(self, script):
        self._js_script = script

    def _on_load_finished(self):
        if self.js_script:
            self.js_timer.start()
        else:
            self.toHtml(self.handle_html)

    def handle_timeout(self):
        self.runJavaScript(
            'document.getElementsByClassName("product-date").length > 0',
            self.handle_run_js,
        )

    def handle_run_js(self, data):
        if data:
            self.toHtml(self.handle_html)
        else:
            self.js_timer.start()

    def handle_html(self, html_str):
        self._html = html_str
        QCoreApplication.quit()


def main():
    page = Page()
    page.js_script = 'document.getElementsByClassName("product-date").length > 0'
    page.start(
        "https://www.hlj.com/gundam-universe-xxxg-01sr-gundam-sandrock-bans61272"
    )
    soup = bs(page.html, "html.parser")
    js_test = soup.find("div", class_="product-date")
    dt_str = js_test.find("span", class_="release-date").text
    print(dt_str)


if __name__ == "__main__":
    main()
 

Ответ №2:

Возможно, детали генерируются динамически, поэтому вы можете попытаться найти данные из xhr и извлечь их из него

Перейдите в режим разработчика Chrome и перейдите на вкладку сеть нажмите на xhr перезагрузите свой веб-сайт, и теперь ссылки появятся data в разделе Имя, содержащем ваши данные в формате json

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

Код:

 import requests

headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
        "referer":"https://www.hlj.com/gundam-universe-xxxg-01sr-gundam-sandrock-bans61272"}

payload={"skus": "BANS61272"}
res=requests.post("https://www.hlj.com/price_inventory/fetch/data",data=payload,headers=headers)


main_data=res.json()
main_data[payload['skus']]["release_date"]
 

Выход:

'May 2021'

Изображение:

введите описание изображения здесь