Парсер сайта аптек
Создал небольшой парсер
import requests
from bs4 import BeautifulSoup
URL = 'https://apteka.ru/vendor/Эгис%20Фармацевтический%20завод%20ЗАО/'
HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
'accept': '*/*'}
HOST = 'https://apteka.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_='catalog-card card-flex')
lp = []
for item in items:
count = item.find('span', class_='light-button__label').get_text(strip=True)
if count == 'Купить':
lp.append({
'name': item.find('a', class_='catalog-card__name').get_text(strip=True),
'vendor': item.find('span', class_='emphasis').get_text(strip=True),
'price': item.find('span', class_='moneyprice__roubles').get_text(strip=True),
'currency': item.find('span', class_='moneyprice__currency').get_text(strip=True),
'link': HOST + item.find('a').get('href')
})
else:
lp.append({
'link': HOST + item.find('a').get('href')
})
return lp
def parse():
html = get_html(URL)
if html.status_code == 200:
lp = get_content(html.text)
print(lp)
else:
print('Error')
parse()
Вопросы:
- на сайте если
count = 'Купить'- значит только одна дозировка, иначе есть выбор. Тогда в массивlpя помещаю толькоlink. Нужно во время работыget_content(html)вызывать поlinkдополнительный вызов или проверять послеparse(), когда массивlpбудет уже сформирован? И как правильнее будет вставить в тот же массив? - как обойти все страницы, а не только первую?
UPDATE:
- ненужный вопрос, поменял структуру, намного лучше теперь и быстрее
- обход исполнил следующим образом (на странице появляется новый класс, если на ней нет карточек товара):
def parse():
i = 1
LP = []
# Для каждой страницы
while get_html(URL, {'page': i}).status_code == 200:
html = get_html(URL, {'page': i})
soup = BeautifulSoup(html.text, 'html.parser')
page = soup.find('div', class_='catalog-empty-response')
# Остановка в случае пустой витрины на странице
if page:
break
else:
lp = get_content(html.text)
LP = LP + lp
i = i + 1
print(LP)
Ответы (1 шт):
Автор решения: KoVadim
→ Ссылка
как обойти все страницы, а не только первую?
есть три подхода:
сформировать все возможные ссылки, выкачать. Но это не всегда возможно.
качать рекурсивно. Когда получили новую ссылку, то просто вызываем функцию "скачивания страницы". Если страниц и вложенности немного, то вполне работает и легко кодируется.
списочный способ. Схематический код
urls_to_download = ["http://start_url"] downloaded_urls = [] # может лучше set? while urls_to_download не пустой: #извлечь один url с списка urls_to_download url = urls_to_download.pop() if url in downloaded_urls: continue new_urls = download(url) # добавить new_urls в urls_to_download urls_to_download = urls_to_download + new_urls #добавить url в список downloaded_urls downloaded_urls.append(url) def download(url): #скачиваем и парсим страницу. page = get(url) #сохраняем в базу/диск save_page(page); #возвращаем список спарсеных с страницы ссылок return extract_urls(page)