Проблема с очисткой веб-страниц с использованием селена и красивого супа

Я создаю сайт сравнения цен для своего университетского проекта. Я пытаюсь распечатать товары и цены с этого сайта https://www.lotuss.com.my/en/category/fresh-produce?sort=relevance:DESC, но у меня возникла ошибка:

Exception has occurred: TypeError
'NoneType' object is not callable
  File "C:\xampp\htdocs\Price\test.py", line 36, in <module>
    grocery_items = soup.findall('div', class_='product-grid-item')
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: 'NoneType' object is not callable

Это код:

from bs4 import BeautifulSoup
import requests
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

chrome_options = Options()

chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")

service = Service(executable_path='C:/chromedriver/chromedriver.exe')
driver = webdriver.Chrome(service=service, options=chrome_options)

# Open the webpage
driver.get('https://www.lotuss.com.my/en/category/fresh-produce?sort=relevance:DESC')

# Wait for the page to fully load
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CSS_SELECTOR, "iframe"))
    )
    print("Please solve the CAPTCHA manually in the opened browser window.")
finally:

    input("Press Enter after solving the CAPTCHA...")

    html_text = driver.page_source

    driver.quit()
soup = BeautifulSoup(html_text, 'lxml')
grocery_items = soup.findall('div', class_='product-grid-item')
grocery_price = soup.findall('span', class_='sc-kHxTfl hwpbzy')

print(grocery_items)
print(grocery_price)

Пометка о закрытии как опечатка.

Andrew Yim 30.07.2024 13:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Ошибка вызвана использованием неправильного метода для объекта супа. Метод должен быть find_all вместо findall.

Код должен быть таким, как показано ниже:

grocery_items = soup.find_all('div', class_='product-grid-item')
grocery_price = soup.find_all('span', class_='sc-kHxTfl hwpbzy')

Я протестировал ваш код и обнаружил еще несколько проблем. После того, как вы исправите ошибку, указанную в этом вопросе, вы можете заметить, что на консоли ничего не печатается. Сделайте, как показано ниже:

  1. По умолчанию селен не открывает браузер в полноэкранном режиме, иногда это может привести к тому, что элементы будут не видны и не удастся найти все целевые элементы. Следовательно, откройте Chrome в полноэкранном режиме, используя приведенный ниже код:

    driver.get('https://www.lotuss.com.my/en/category/fresh-produce?sort=relevance:DESC')
    driver.maximize_window()
    
  2. Последняя строка вашего кода просто печатает HTML.

    print(grocery_items)
    print(grocery_price)
    

    Вместо этого вам нужно распечатать текстовые значения HTML. Используйте код, как показано ниже:

    for item in grocery_items:
        print(item.get_text(strip=True))
    
    for price in grocery_price:
        print(price.get_text(strip=True))
    

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

Darren Ch'ng 31.07.2024 02:35

Selenium может очищать только те элементы, которые загружены и видны на экране. Чтобы продолжить парсинг, вам нужно прокрутить страницу вниз и загрузить элементы.

Shawn 31.07.2024 10:07

Ошибка в вашем коде связана с вызовом soup.findall. Вам придется заменить это вызовом soup.find_all или, что еще лучше, использовать CSS-селекторы напрямую с BS4 с помощью soup.select.

Глядя на веб-сайт, кажется, что вы можете использовать внутренний API для прямого получения данных и пропустить анализ HTML из Selenium.

import json

import requests

url = "https://api-o2o.lotuss.com.my/lotuss-mobile-bff/product/v2/products"
headers = {"Accept-Language": "en"}
q = {
    "offset": 0,
    "limit": 300,
    "filter": {
        "categoryUrlKey": "fresh-produce",
    },
    "websiteCode": "malaysia_hy",
}
q = json.dumps(q)
response = requests.get(url, headers=headers, params = {"q": q})
response.raise_for_status()

Вы можете поиграть со значениями предела и смещения, чтобы перебирать разные результаты.

Лучший!

Другие вопросы по теме

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

Как сгруппировать части маски в изображении с помощью Python?
Как подсчитать длину строки в Python (если строка содержит экранирование символов)?
Как мне найти максимальное значение динамического окна и минимальное значение ниже него?
Как изменить цвет определенного слова пользователя в «input()»
C-расширение Python с numpy случайно аварийно завершает работу после нескольких вызовов (5–10) из кода Python
Создайте фабрику виджетов в Qt
Почему GEKKO не предоставляет оптимальные команды, хотя выходные данные не соответствуют эталонным?
Java sshtools сгенерировал подпись EDDSA, не совпадающую с сгенерированной подписью пикриптома Python
Как записать атрибуты каждого экземпляра в переменную класса, при этом родительский класс записывает экземпляры всех классов в одну и ту же переменную?
Создание динамического массива numpy с использованием двух существующих массивов