Парсер. BS4. немного запутался в функциях, подскажите пожалуйста, что не так?
Не так давно изучаю Python, пишу свой первый парсер, хочу брать цены на одно оборудование с одного сайта)
все просто. Одна функция загружает документ, другая собирает ссылки с главной страницы, третья собирает название и цену с конкретного товара 4я записывает в CSV.
почему то третья функция проходится по главной стр, и не видит ссылки собранные во второй в список links. что я сделал не так, как передать этот список в 3ю функцию чтобы она проходила по нему а не по главной?
import requests
from bs4 import BeautifulSoup
import csv
def get_html(url): # получаем HTML код
req = requests.get(url=url)
return req.text
def get_links(html): # получаем список ссылок с главной страницы
soup = BeautifulSoup(html, "lxml")
links_bad = soup.find_all(class_='title-sc')
links = []
for i in links_bad:
a = i.find('a').get('href')
link_good = 'https://tdlider.ru' + a
links.append(link_good)
return links
def item_data(html): # получаем информацию с каждой ссылки
soup = BeautifulSoup(html, 'lxml')
try:
name = soup.find('div', class_="tovar-title").find('h1').text
except:
name = "нет имени"
try:
price = soup.find('div', class_="post-price").text
except:
price = "Нет цены"
data = {"name": name,
"price": price
}
return data
def write_csv(data): # Пишем все в CSV
with open("pricelist_lider.csv", "w", newline='') as file:
writer = csv.writer(file)
writer.writerow
(
(data['name'],
data['price'])
)
print(data['name'], 'parsed')
def main(): # Главная функция, которая собирает все.
url = 'https://tdlider.ru'
all_links = get_links(get_html(url))
for url in all_links:
if url != "https://tdlider.ru#":
html = get_html(url)
data = item_data(html)
write_csv(data)
if __name__ == "__main__":
main()
Ответы (1 шт):
Ссылки парсер собирает корректно, в нём другие проблемы:
- Неправильный режим открытия файла, с режимом "w" файл будет перезаписываться, а не добавлять строки, поменяйте режим на "a" в функции write_csv, чтобы строки добавлялись. Или предварительно соберите все данные в один список и один раз запишите.
- Вы пытаетесь не тот элемент найти, он существует на странице конкретного товара, а не в каталоге.
Самое первое решение вопроса что пришло мне в голову это вытащить все блоки с товарами, а затем наименование и цену:
def item_data(html):
data_list = []
soup = BeautifulSoup(html, 'lxml')
cells = soup.find_all("div", class_="cat-post-cell")
for cell in cells:
name = cell.find("div", class_="title").text
price = cell.find("div", class_="post-price")
if price:
price = price.text
else:
price = "Нет цены"
data_list.append([name, price])
return data_list
Код немного изменился, и вместо словаря передаются вложенные списки и запись в csv будет выглядеть так:
def write_csv(data):
with open("pricelist_lider.csv", "a", newline='') as file:
writer = csv.writer(file)
for line in data:
writer.writerow(line)
print(line[0], "parsed")