Как извлечь данные из графика с веб-страницы?

#python-3.x #web-scraping #beautifulsoup #python-requests

#python-3.x #очистка веб-страниц #beautifulsoup #python-запросы

Вопрос:

Я пытаюсь очистить данные графика с веб-страницы: ‘https://cawp.rutgers.edu/women-percentage-2020-candidates ‘

Я попробовал приведенный ниже код для извлечения данных из графика:

 import requests
from bs4 import BeautifulSoup

Res = requests.get('https://cawp.rutgers.edu/women-percentage-2020-candidates').text
soup = BeautifulSoup(Res, "html.parser")

Values= [i.text for i in soup.findAll('g', {'class': 'igc-graph'}) if i]
Dates = [i.text for i in soup.findAll('g', {'class': 'igc-legend-entry'}) if i]

print(Values, Dates) ## both list are empty
Data= pd.DataFrame({'Value':Values,'Date':Dates}) ## Returning an Empty Dataframe
  

Я хочу извлечь дату и значение из всех 4 гистограмм. Пожалуйста, кто-нибудь подскажет, что мне нужно сделать здесь, чтобы извлечь данные графика, или есть какой-либо другой метод, которым я могу попытаться извлечь данные. Спасибо;

Ответ №1:

Этот график был расположен по этому URL : https://e.infogram.com/5bb50948-04b2-4113-82e6-5e5f06236538

Вы можете найти идентификатор инфограммы (путь к целевому URL-адресу) непосредственно в исходном URL-адресе, если вы ищете div с классом, infogram-embed который имеет значение атрибута data-id :

 <div class="infogram-embed" data-id="5bb50948-04b2-4113-82e6-5e5f06236538" data-title="Candidate Tracker 2020_US House_Proportions" data-type="interactive"> </div>
  

С этого URL-адреса он загружает статический JSON в javascript. Вы можете использовать регулярное выражение, чтобы извлечь его и проанализировать структуру JSON, чтобы получить строку / столбец и разные таблицы:

 import requests
from bs4 import BeautifulSoup
import re
import json

original_url = "https://cawp.rutgers.edu/women-percentage-2020-candidates"
r = requests.get(original_url)
soup = BeautifulSoup(r.text, "html.parser")

infogram_url = f'https://e.infogram.com/{soup.find("div",{"class":"infogram-embed"})["data-id"]}'
r = requests.get(infogram_url)
soup = BeautifulSoup(r.text, "html.parser")

script = [
    t 
    for t in soup.findAll("script") 
    if "window.infographicData" in t.text
][0].text

extract = re.search(r".*window.infographicData=(.*);$", script)

data = json.loads(extract.group(1))

entities = data["elements"]["content"]["content"]["entities"]

tables = [
    (entities[key]["props"]["chartData"]["sheetnames"], entities[key]["props"]["chartData"]["data"])
    for key in entities.keys()
    if ("props" in entities[key]) and ("chartData" in entities[key]["props"])
]

data = []
for t in tables:
    for i, sheet in enumerate(t[0]):
        data.append({
            "sheetName": sheet,
            "table": dict([(t[1][i][0][j],t[1][i][1][j])  for j in range(len(t[1][i][0])) ])
        })
print(data)
  

Выходной сигнал:

 [{'sheetName': 'Sheet 1',
  'table': {'': '2020', 'Districts Already Filed': '435'}},
 {'sheetName': 'All',
  'table': {'': 'Filed', '2016': '17.8%', '2018': '24.2%', '2020': '29.1%'}},
 {'sheetName': 'Democrats Only',
  'table': {'': 'Filed', '2016': '25.1%', '2018': '32.5%', '2020': '37.9%'}},
 {'sheetName': 'Republicans Only',
  'table': {'': 'Filed', '2016': '11.5%', '2018': '13.7%', '2020': '21.3%'}}]