Сортировка списка в парсере
Пишу парсер, который собирает информацию о валютах вот с этого сайта - https://www.banki.ru/products/currency/cb/
В процессе я все таки смог извлечь данные о валютах, однако возникли проблемы с сортировкой, вот полный код:
from bs4 import BeautifulSoup
import requests
import re
url = 'https://www.banki.ru/products/currency/cb/'
req = requests.get(url)
soup = BeautifulSoup(req.text, features='html.parser')
cost = soup.find_all('tr')
def clean(obj):
t = []
for i in obj:
t.append(re.sub('[\t\n]', '', i.text))
return t
print(clean(cost))
На выходе я получаю список со всеми валютами и их атрибутами, однако в не совсем удобном виде, мне требуется:
- Отсортировать список, чтобы в нем остались только элементы, начинающиеся с трех заглавных букв
- Создать текстовый файл со значениями вида <Название валюты> <Код> <Цена> <Изменение цены>
Можете внести какие то улучшения в код в плане самого парсинга, так как это мой первый опыт работы с бс4, регулярными выражениями и html в целом.
Ответы (1 шт):
Автор решения: gil9red
→ Ссылка
Лучше парсером вытаскивать нужные поля, тогда не придется делать пост-обработку.
Кст:
- Метод
selectпринимает css-селектор - А выражение
tbody > tr[data-currency-code]означает поиск всехtr, имеющих атрибутdata-currency-codeи у которых в родителях тегtbody
Попробуйте:
from bs4 import BeautifulSoup
import requests
url = 'https://www.banki.ru/products/currency/cb/'
rs = requests.get(url)
root = BeautifulSoup(rs.content, 'html.parser')
for tr in root.select('tbody > tr[data-currency-code]'):
td_items = tr.select('td')
code, num, name, value, change = \
map(lambda x: x.get_text(strip=True), td_items)
print(code, num, name, value, change)
Результат:
USD 1 Доллар США 73.4261 +0,0628
EUR 1 Евро 87.2889 +1,0357
AUD 1 Австралийский доллар 52.8154 +0,4633
...
ZAR 10 Южноафриканский рэнд 43.4922 -0,2144
JPY 100 Японская иена 70.1870 +0,3803
А чтобы это выгрузить в файл, предлагаю использовать csv.
Пример:
import csv
from bs4 import BeautifulSoup
import requests
url = 'https://www.banki.ru/products/currency/cb/'
rs = requests.get(url)
root = BeautifulSoup(rs.content, 'html.parser')
with open('currency.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.writer(f)
writer.writerow(['<Название валюты>', '<Код>', '<Цена>', '<Изменение цены>'])
for tr in root.select('tbody > tr[data-currency-code]'):
td_items = tr.select('td')
code, num, name, value, change = \
map(lambda x: x.get_text(strip=True), td_items)
writer.writerow([name, code, value, change])
Получится файл:
<Название валюты>,<Код>,<Цена>,<Изменение цены>
Доллар США,USD,73.4261,"+0,0628"
Евро,EUR,87.2889,"+1,0357"
Австралийский доллар,AUD,52.8154,"+0,4633"
Азербайджанский манат,AZN,43.2172,"+0,0369"
Армянский драм,AMD,15.0958,"-0,0494"
Белорусский рубль,BYN,30.0890,"+0,0073"
...