Как собрать текст «td» из списка списков и добавить его в словарь python BeautifulSoup

#python #pandas #dataframe #dictionary #beautifulsoup

#питон #панды #фрейм данных #словарь #прекрасный суп

Вопрос:

Здесь я пытаюсь получить значение каждого столбца в таблице, показанной на рисунке (для трех разных страниц), и сохранить их в фрейме данных pandas. Я собрал данные, и теперь у меня есть список списков, но когда я пытаюсь добавить их в словарь, я получаю пустой словарь. может ли кто-нибудь помочь мне понять, что я делаю неправильно, или предложить альтернативный способ создания 3 кадров данных, по одному для каждой таблицы? введите описание изображения здесь

Вот мой код:

 import numpy as np import pandas as pd from datetime import datetime import pytz import requests import json from bs4 import BeautifulSoup  url_list = ['https://www.coingecko.com/en/coins/ethereum/historical_data/usd?start_date=2021-08-06amp;end_date=2021-09-05#panel',  'https://www.coingecko.com/en/coins/cardano/historical_data/usd?start_date=2021-08-06amp;end_date=2021-09-05#panel',  'https://www.coingecko.com/en/coins/chainlink/historical_data/usd?start_date=2021-08-06amp;end_date=2021-09-05#panel']   results = []   for url in url_list:  response = requests.get(url)  src = response.content  soup = BeautifulSoup(response.text , 'html.parser')  results.append(soup.find_all( "td",class_= "text-center"))   collected_data = dict()   for result in results:  for r in result:  datas = r.find_all("td", title=True)   for data in datas:  collected_data.setdefault(data.text)   collected_data  

Ответ №1:

Что происходит?

В вашем первом for loop вы только добавляете результирующий набор soup.find_all( "td",class_= "text-center") to results .

Так что вы не найдете то, что ищете, с помощью datas = r.find_all("td", title=True)

Обратите также внимание, что заголовки столбцов помещаются не в lt;tdgt; , а в lt;thgt; .

Как это исправить?

Вы могли бы выбрать более конкретные, все lt;trgt; , lt;tbodygt; чтобы повторить:

 for row in soup.select('tbody tr'):  

Во время итерации выберите lt;thgt; и lt;tdgt; и zip() это dict() в списке заголовков столбцов:

 data.append(  dict(zip([x.text for x in soup.select('thead th')], [x.text.strip() for x in row.select('th,td')]))  )  

Пример

 import pandas as pd import requests from bs4 import BeautifulSoup  url_list = ['https://www.coingecko.com/en/coins/ethereum/historical_data/usd?start_date=2021-08-06amp;end_date=2021-09-05#panel',  'https://www.coingecko.com/en/coins/cardano/historical_data/usd?start_date=2021-08-06amp;end_date=2021-09-05#panel',  'https://www.coingecko.com/en/coins/chainlink/historical_data/usd?start_date=2021-08-06amp;end_date=2021-09-05#panel']  data = []  for url in url_list:  response = requests.get(url)  src = response.content  soup = BeautifulSoup(response.text , 'html.parser')    for row in soup.select('tbody tr'):    data.append(  dict(zip([x.text for x in soup.select('thead th')], [x.text.strip() for x in row.select('th,td')]))  )   pd.DataFrame(data)  

Выход

Дата Рыночная капитализация Объем Открыть Закрыть
2021-09-05 $456,929,768,632 $24,002,848,309 $3,894.94 N/A
2021-09-04 $462,019,852,288 $30,463,347,266 $3,936.16 $3,894.94
2021-09-03 $444,936,758,975 $28,115,776,510 $3,793.30 $3,936.16

Редактировать

Чтобы получить фрейм данных по URL — адресу, вы можете изменить код на следующий-он добавит фреймы в список, чтобы вы могли повторять действия.

Обратите внимание, что это основано на вашем комментарии, и если он подходит, хорошо. Я бы предложил хранить поставщика монет также в виде столбца, чтобы вы могли фильтровать, группировать по … по всем поставщикам, но это следует задать в новом вопросе, если это имеет значение.

 dfList = []  for url in url_list:  response = requests.get(url)  src = response.content  soup = BeautifulSoup(response.text , 'html.parser')    data = []  coin = url.split("/")[5].upper()  for row in soup.select('tbody tr'):    data.append(  dict(zip([f'{x.text}_{coin}' for x in soup.select('thead th')], [x.text.strip() for x in row.select('th,td')]))  )  # if you like to save directly as csv... change next line to -gt; pd.DataFrame(data).to_csv(f'{coin}.csv')  dfList.append(pd.DataFrame(data))  

Выход

Выберите, например, фрейм данных по индексу списка dfList[0]

Дата-эфир Рыночная капитал_этериум объем_этериум Open_этериум Закрыть эфир
2021-09-05 $456,929,768,632 $24,002,848,309 $3,894.94 N/A
2021-09-04 $462,019,852,288 $30,463,347,266 $3,936.16 $3,894.94

Комментарии:

1. Спасибо за ответ, это идеально, но я хотел создать 3 таблицы со столбцами формата ‘Market Cap_CURRENCYX’, ‘Volume_CURRENCYX’, ‘Open_CURRENCYX’, ‘Close_CURRENCYX’, ‘Market Cap_CURRENCYY’, ‘Volume_CURRENCYY’, ‘Open_CURRENCYY’, ‘Close_CURRENCYY’, … для каждого.

2. Не могли бы вы, случайно, помочь мне и в этом тоже?