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

Я создаю сайт сравнения цен для своего университетского проекта. Я пытаюсь распечатать товары и цены с этого сайта 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)

🤔 А знаете ли вы, что...
С Python можно создавать кросс-платформенные приложения для Windows, macOS и Linux.


50
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))
    

Ошибка в вашем коде связана с вызовом 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()

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

Лучший!