Я пытаюсь получить доллары и цены на мой школьный проект. Поэтому я решил использовать для этого парсинг веб-страниц, но у меня возникла проблема. Когда я пытаюсь использовать свой код на сервере, он выдает ошибку 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». Это ничего не меняет.
Это потому, что soup.find("div", {"class": "container yf-mgkamr"})
возвращает None. Если вы можете поделиться анализируемым HTML-кодом, это будет полезно. Но он не находит элементов div
с class = "container yf-mgkamr"
.
@nbk Готово! Да, как я уже говорил, HTML не содержит <div class = "container yf-mgkamr">...</div>
Зачем ты вообще это царапаешь? Он даже не возвращает HTML, он возвращает JSON @nbk
он хочет получить некоторую сумму в долларах, поэтому для хорошего ответа вы должны найти ее
Вероятно, вам следует использовать это
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? это особый метод?
в режиме проверки — Сеть
Этот подход не сработает. Сначала я покажу почему, а потом напишу решение.
#! /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'
Несколько вещей, которые я заметил
проверьте, существует ли этот HTML-тег «класс»: «контейнер yf-mgkamr».
Этот код ниже может быть проблемой, возможно, вы получаете доступ к индексу, который не существует.
dolar = Soup.find("div", {"class": "container yf-mgkamr"}).find_all("span")[0].text
Сайт мог вас выгнать.
почему бы не запустить код, URL-адрес которого уже есть?