Не могу понять что тут не так
Код:
import requests
from bs4 import BeautifulSoup
URL = 'https://auto.ru/schelkovo/cars/hyundai/used/'
HEADERS = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
'accept': '*/*'}
HOST = 'https://auto.ru'
def get_html(url, params=None):
r = requests.get(url, headers=HEADERS, params=params)
return r
def get_content(html):
soup = BeautifulSoup(html, 'html.parser')
items = soup.find_all('div', class_='ListingItem')
cars = []
for item in items:
cars.append({
'title': item.find('h3', class_='ListingItemTitle ListingItem_title').get_text(strip=True),
'link': HOST + item.find('a', class_='Link ListingItemTitle_link').get('href'),
'rub_price': item.find('div', class_='ListingItem_columnCellPrice').get_text(),
'city': item.find('div', class_='ListingItem__additionalInfo').find_next('span').get_text(), })
return cars
def parse():
html = get_html(URL)
if html.status_code == 200:
cars = get_content(html.text)
else:
print('Error')
Ошибка:
Traceback (most recent call last):
File "C:\Users\User\PycharmProjects\parse\main.py", line 38, in <module>
parse()
File "C:\Users\User\PycharmProjects\parse\main.py", line 33, in parse
cars = get_content(html.text)
File "C:\Users\User\PycharmProjects\parse\main.py", line 23, in get_content
'title': item.find('h3', class_='ListingItemTitle ListingItem_title').get_text(strip=True),
AttributeError: 'NoneType' object has no attribute 'get_text'
Process finished with exit code 1
Ответы (2 шт):
Автор решения: Сергей Шашко
→ Ссылка
В функций get_content переменная items принимает значенние пустой список
Автор решения: gil9red
→ Ссылка
Переписал код парсера
Основные различия:
- Использование
Sessionдля запросов. Этот объект использует заголовки запроса, что ему укажешь, и можно дополнительно передавать через параметрheaders=. Плюс, он помнит куки, что полезно - Для склеивания ссылок лучше использовать
urljoin, а ссылку можно брать из ответа на запросrs(если на сайте будет редирект, типа сhttpнаhttpsили на другой домен, то вrs.urlбудет актуальный адрес) - Использование css-селекторов в методах
selectиselect_one. Они простые и повсеместно используются - Цену решил парсить как целое число, для тех машин, у которых цены нет, будет возвращено 0, но ничего не мешает возвращать
Noneили что-то аналогичное
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup
def get_price(tag) -> int:
try:
# Оставляем только цифры
value = ''.join(c for c in tag.get_text() if c.isdigit())
return int(value)
except:
return 0
session = requests.Session()
session.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
session.headers['Accept'] = '*/*'
url = 'https://auto.ru/schelkovo/cars/hyundai/used/'
rs = session.get(url)
root = BeautifulSoup(rs.content, 'html.parser')
for item in root.select('.ListingItem'):
title_el = item.select_one('.ListingItemTitle__link[href]')
title = title_el.get_text(strip=True)
url = urljoin(rs.url, title_el['href'])
price_el = item.select_one('.ListingItemPrice__content')
price = get_price(price_el)
region_el = item.select_one('.MetroListPlace__regionName')
city = region_el.get_text() if region_el else '-'
print(f'{title!r}, {price}, {city!r}')
print(url)
print()
Результат:
'Hyundai Solaris I Рестайлинг', 810000, 'Тейково (180\xa0км от\xa0Щелково)'
https://auto.ru/cars/used/sale/hyundai/solaris/1105856012-839475dc/?geo_id=10765
'Hyundai Tucson IV', 3600000, 'Москва'
https://auto.ru/cars/used/sale/hyundai/tucson/1105942340-1686d5bc/?geo_id=10765
'Hyundai Grand Starex I Рестайлинг', 2385000, 'Москва'
https://auto.ru/cars/used/sale/hyundai/grand_starex/1105479054-60792926/?geo_id=10765
...
'Hyundai Sonata IV (EF) Рестайлинг', 245000, 'Москва'
https://auto.ru/cars/used/sale/hyundai/sonata/1105669699-a55923b6/?geo_id=10765
'Hyundai Elantra III (XD2) Рестайлинг', 289000, 'Москва'
https://auto.ru/cars/used/sale/hyundai/elantra/1105696908-ffede62d/?geo_id=10765