Веб-скрапинг для получения данных с помощью Python NoneType ОШИБКА

Я пытаюсь получить доллары и цены на мой школьный проект. Поэтому я решил использовать для этого парсинг веб-страниц, но у меня возникла проблема. Когда я пытаюсь использовать свой код на сервере, он выдает ошибку NoneType. Он работает в Google Colab, но я не могу использовать его на своем компьютере или сервере. Как я могу решить эту проблему, ребята?

Веб-скрапинг-код;

def dolar():
  headers = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15'
  url = f'https://finance.yahoo.com/quote/TRY=X/'
  r = requests.get(url)
  soup = bs(r.text, 'html.parser')
  dolar = soup.find("div", {"class": "container yf-mgkamr"}).find_all("span")[0].text
  return dolar

ЭРООР ;

Traceback (most recent call last):
  File "/Users/user/Desktop/API/main.py", line 38, in <module>
    dolar()
  File "/Users/user/Desktop/API/main.py", line 35, in dolar
    dolar = soup.find("div", {"class": "container yf-mgkamr"}).find_all("span")[0].text
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'find_all'
(.venv) user@192 API % 

Я пытался изменить свой основной сайт, пытался использовать без метода «.find_all». Это ничего не меняет.

Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
70
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это потому, что soup.find("div", {"class": "container yf-mgkamr"}) возвращает None. Если вы можете поделиться анализируемым HTML-кодом, это будет полезно. Но он не находит элементов div с class = "container yf-mgkamr".

почему бы не запустить код, URL-адрес которого уже есть?

nbk 27.07.2024 22:57

@nbk Готово! Да, как я уже говорил, HTML не содержит <div class = "container yf-mgkamr">...</div>

psilocybin 27.07.2024 23:55

Зачем ты вообще это царапаешь? Он даже не возвращает HTML, он возвращает JSON @nbk

psilocybin 28.07.2024 00:01

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

nbk 28.07.2024 00:06
Ответ принят как подходящий

Вероятно, вам следует использовать это

import requests
import time


def dolar():
    now = time.time() - 10
    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15"
    }
    url = f"https://query1.finance.yahoo.com/v8/finance/chart/TRY=X?period1 = {int(now)}&period2 = {int(now)}"
    response = requests.get(url, headers=headers)
    return response.json()['chart']['result'][0]['meta']['regularMarketPrice']


print(dolar())

как я могу получить эту ссылку query1? это особый метод?

Wusi 28.07.2024 15:38

в режиме проверки — Сеть

Khaliknazar 28.07.2024 23:28

Этот подход не сработает. Сначала я покажу почему, а потом напишу решение.

#! /usr/bin/env python

from bs4 import BeautifulSoup as bs
import requests
from structlog import get_logger

logger = get_logger()

def dolar()->str:
    headers:str = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15'
    url    :str = 'https://finance.yahoo.com/quote/TRY=X/'
    r           = requests.get(url)
    soup        = bs(r.text, 'html.parser')
    _div        = soup.find("div", {"class": "container yf-mgkamr"})
    try:
        _spans  = _div.find_all("span") # listen to Psilocybin
    except AttributeError as error:     # this error is always thrown
        logger.error(error)             # inform the user that it didn't work
        return r.text                   # show the user why it didn't work
    _span       = _spans[0]
    dolar  :str = _span.text
    return dolar
result:str = dolar()
logger.debug(result)

Вы можете запустить наш код без grep и убедиться, что в HTML нет ожидаемых данных.

./so.py|grep -ie span -e div -q || echo no spans or divs found
no spans or divs found

Хорошо, теперь давайте получим эти данные для вас.

Я скопировал скрипт входа в систему, удалил все интересные вещи и вставил xpath из изображения. Для вашего удобства.

    async def run()->Optional[str]:
        _url             :str             = 'https://finance.yahoo.com/quote/TRY=X/'
        mean_arrival_rate:Optional[float] = None

        def helper(driver:WebDriver)->Optional[str]:
            """
            Parse it:

            <fin-streamer class = "livePrice yf-mgkamr" data-symbol = "TRY=X" data-testid = "qsp-price" data-field = "regularMarketPrice" data-trend = "none" data-pricehint = "4" data-value = "32.9042" active = ""><span>32.9042</span></fin-streamer>
            """

            logger.debug('grab url')
            driver.get(_url) # TODO params, headers, auth       
            driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")            # get the whole page; you don't need this
            logger.debug('loaded page %s', _url)

            _price = find_element(driver, None, # don't need to make it think we're not a bot, so no wait time
                (By.XPATH, "//fin-streamer[@data-symbol='TRY=X']"), # any one of these *should* work
                (By.XPATH, "//fin-streamer[@data-testid='qsp-price']"), # the other script uses an LLM to generate these
                (By.XPATH, "//fin-streamer[@data-field='regularMarketPrice']"), # that's too big and expensive to be useful
                fallback=None) # fallback is used to press 'enter' when clicking 'next' fails. don't worry about it
            return _price.get_attribute('data-value')
        try:
            async with selenium_async.use_browser(options=options, pool=pool) as driver:
                result:Optional[str] = await asyncio.to_thread(helper, driver)
                await logger.ainfo('result: %s', result)
        except AttributeError as error:
            logger.error(error)
        return result

Это некрасиво, но возвращает то, что вы хотите.

2024-07-27 17:11:01 [debug    ] grab url                      
2024-07-27 17:11:05 [debug    ] loaded page https://finance.yahoo.com/quote/TRY=X/
2024-07-27 17:11:05 [debug    ] find_element                  
2024-07-27 17:11:05 [debug    ] searching xpath //fin-streamer[@data-symbol='TRY=X']
2024-07-27 17:11:06 [info     ] result: 32.9042               
2024-07-27 17:11:06 [error    ] 'WebDriver' object has no attribute 'get_blank'

Несколько вещей, которые я заметил

  1. проверьте, существует ли этот HTML-тег «класс»: «контейнер yf-mgkamr».

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

    dolar = Soup.find("div", {"class": "container yf-mgkamr"}).find_all("span")[0].text

  3. Сайт мог вас выгнать.

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