J'essaie de gratter des données relatives à Covid-19. J'ai pu télécharger certaines données du site Web, par exemple, le nombre de cas totaux, mais pas les données provenant de graphiques interactifs.
Je grattez habituellement des graphiques interactifs avec JSON en trouvant la source de «réseau» dans la page d'élément d'inspection. Cependant, je n'ai pas pu trouver le «réseau» pour les graphiques interactifs à gratter. P>
Quelqu'un peut-il m'aider s'il vous plaît à gratter les données de "décès total"? ou tout autre graphique du site Web. Merci. P>
Juste pour le rendre clair. Je ne veux pas gratter des données de la table des pays. Je l'ai déjà fait ça. Ce que je veux faire, c'est d'obtenir des données des graphiques. Par exemple, les données du graphique de ratio de décès vs Date ou des cas actifs VS Date Graphique. p>
merci p> Par exemple, nombre de pays effectés: p> Site Web P> P>
3 Réponses :
Voici ma prise sur ceci: strong> Premièrement, vous devez d'abord obtenir la table sous forme de tableau NUMPY: P> import requests
from bs4 import BeautifulSoup
import numpy as np
def convertDigit(string):
if string.replace(",", "").isdigit():
return int(string.replace(",", ""))
return string
url = 'https://www.worldometers.info/coronavirus/#countries'
r = requests.get(url)
soup = BeautifulSoup(r.text, "html.parser") # Parse html
table = soup.find("table", {"id": "main_table_countries"}).find_all("tbody") # table
tr_elems = table[0].find_all("tr") # All rows in table
data = []
for tr in tr_elems: # Loop through rows
td_elems = tr.find_all("td") # Each column in row
data.append([convertDigit(td.text.strip()) for td in td_elems])
np_array = np.array(data)
Merci pour votre réponse, mais je ne veux pas gratter les données de la table. Ce que je veux faire, c'est d'obtenir des données du graphique. Par exemple, les données du graphique ratio de décès vs date.
D'accord, alors piquer dans le code, j'ai vu que les graphiques ont été générés avec ce module nommé Highcharts code>. J'ai cherché ça sur Google et a trouvé Ce . Espérons que cela vous aide!
J'ai utilisé des informations de votre lien pour créer un exemple dans ma réponse, merci. Et plus tard, j'ai trouvé les mêmes données que la table sur la sous-pompage Worldomètres.info/coronavirus/coronavirus- mort-péage . C'est quelque chose d'utile pour votre réponse.
@Furas Nous avons besoin de données quotidiennes sage par pays pour les variables telles que les décès, confirmés, actifs, récupérés
@Maliks Vous avez une table avec des pays sur Worldomètres.info/coronavirus/#Countries - Si vous Lisez cette table tous les jours, alors vous aurez des données quotidiennes. Ou est arrivé à GitHub avec quotidiennement .csv Github.com/cssegisanddata/covid- 19 / Arbre / Master / ...
@furas, mais ce lien GitHub appartient à John Hopkins en tant que source de données, je suppose, pas les Worldomètres, j'ai besoin de données de Worldomètres comme sur ce Worldomètres.info/coronavirus/country/switzerland , nous avons quelques graphiques 4-5, j'ai besoin des données derrière ces graphiques car ces données ne sont pas disponibles dans le formulaire de tableau sur la Worldomeers Site Web ou ailleurs, s'il est sous forme tabulaire ou formulaire CSV, veuillez partager avec moi
@Maliks Pourquoi perdre du temps pour obtenir des données de la carte si vous avez des fichiers CSV sur GitHub. Et si vous devez réadlier de l'obtenir de Worldomètres, vous devrez obtenir des données de highchart.chart (....) code> (comme dans ma réponse) car il n'y a pas d'autres données.
@MALIKS BTW: Les données sur GitHub n'appartiennent pas à John Hopkins, mais à l'université de nom John Hopkins.
@Maliks BTW: Au bas de la page GitHub, première source, vous pouvez voir "Organisation mondiale de la santé (OMS)" code>. Au bas de Worldomètres Page Worldomètres.info/coronavirus comme première source que vous pouvez également voir
"Organisation mondiale de la santé (OMS)" code>
@Maliks BTW: Si vous avez besoin de la Suisse, alors sur votre page Worldomètres.info/coronavirus/country/switzerland `Il existe des liens dans" DerniersUpdates "à la page source rsalzer.github.io/covid_19_ch et il a un lien vers github github.com/rsalzer/covid_19_ch et il a un lien vers GitHub avec CSV pour Kantons Suisse github.com/openzh/covid_19/tree/master/...
Comme je l'ai mentionné dans un commentaire, il y a peu de javascripts avec La plupart d'entre eux ont besoin de trouver des éléments manuellement dans des données et de créer des index corrects ou XPath pour obtenir une valeur. Donc, ce n'est pas si facile. P> Le plus facile était d'utiliser Le plus difficile était d'utiliser résultat p> highchart.chart (....) code> J'ai donc essayé d'obtenir des valeurs en utilisant une méthode différente.
js2xml code> que j'ai vu dans @ayushgarg link Puis-je gratter les données brutes de HighChartChart.js? P>
pyjsparser code> p>
import requests
from bs4 import BeautifulSoup
import json
#import dirtyjson
import js2xml
import pyjsparser
# --- functions ---
def test_eval(script):
print('\n--- eval ---\n')
# chart values
text = script.split('data: [', 1)[1] # beginning
text = text.split(']', 1)[0] # end
values = eval(text) # it creates tuple
print(values)
# title
# I split `yAxis` because there is other `title` without text
# I split beginning in few steps because text may have different indentations (different number of spaces)
# (you could use regex to split in one step)
text = script.split("title: {\n", 1)[1] # beginning
text = text.split("text: '", 1)[1] # beginning
title = text.split("'", 1)[0] # end
print('\ntitle:', title)
text = script.split("yAxis: {\n", 1)[1] # beginning
text = text.split("title: {\n", 1)[1] # beginning
text = text.split("text: '", 1)[1] # beginning
title = text.split("'", 1)[0] # end
print('\ntitle:', title)
def test_json(script):
print('\n--- json ---\n')
# chart values
text = script.split('data: [', 1)[1] # beginning
text = text.split(']', 1)[0] # end
text = '[' + text + ']' # create correct JSON data
values = json.loads(text) # this time doesn't need `dirtyjson`
print(values)
# title
# I split `yAxis` because there is other `title` without text
# I split beginning in few steps because text may have different indentations (different number of spaces)
# (you could use regex to split in one step)
text = script.split("title: {\n", 1)[1] # beginning
text = text.split("text: '", 1)[1] # beginning
title = text.split("'", 1)[0] # end
print('\ntitle:', title)
text = script.split("yAxis: {\n", 1)[1] # beginning
text = text.split("title: {\n", 1)[1] # beginning
text = text.split("text: '", 1)[1] # beginning
title = text.split("'", 1)[0] # end
print('\ntitle:', title)
def test_js2xml(script):
print('\n--- js2xml ---\n')
data = js2xml.parse(script)
# chart values (short and nice path)
values = data.xpath('//property[@name="data"]//number/@value')
#values = [int(x) for x in values] # it may need to convert to int() or float()
#values = [float(x) for x in values] # it may need to convert to int() or float()
print(values)
# title (short and nice path)
#print(js2xml.pretty_print(data.xpath('//property[@name="title"]')[0]))
#title = data.xpath('//property[@name="title"]//string/text()')
#print(js2xml.pretty_print(data.xpath('//property[@name="yAxis"]//property[@name="title"]')[0]))
title = data.xpath('//property[@name="title"]//string/text()')
title = title[0]
print('\ntitle:', title)
title = data.xpath('//property[@name="yAxis"]//property[@name="title"]//string/text()')
title = title[0]
print('\ntitle:', title)
def test_pyjsparser(script):
print('\n--- pyjsparser ---\n')
data = pyjsparser.parse(script)
print("body's number:", len(data['body']))
for number, body in enumerate(data['body']):
if (body['type'] == 'ExpressionStatement'
and body['expression']['callee']['object']['name'] == 'Highcharts'
and len(body['expression']['arguments']) > 1):
arguments = body['expression']['arguments']
#print(json.dumps(values, indent=2))
for properties in arguments[1]['properties']:
#print('name: >{}<'.format(p['key']['name']))
if properties['key']['name'] == 'series':
values = properties['value']['elements'][0]
values = values['properties'][-1]
values = values['value']['elements'] # a lot of work to find it
#print(json.dumps(values, indent=2))
values = [x['value'] for x in values]
print(values)
# title (very complicated path)
# It needs more work to find correct indexes to get title
# so I skip this part as too complex.
# --- main ---
url= 'https://www.worldometers.info/coronavirus/#countries'
r = requests.get(url)
#print(r.text)
soup = BeautifulSoup(r.text, "html.parser")
all_scripts = soup.find_all('script')
print('number of scripts:', len(all_scripts))
for number, script in enumerate(all_scripts):
#if 'data: [' in script.text:
if 'Highcharts.chart' in script.text:
print('\n=== script:', number, '===\n')
test_eval(script.text)
test_json(script.text)
test_js2xml(script.text)
test_pyjsparser(script.text)
Ceci échoue à: script = scripts [24] .text
Je l'ai remplacé par script = scripts [21].
@Richardsandoz Page Change Structure - Vous pouvez voir certaines modifications sur mon blog: Cross: Comment obtenir des données de la parcelle interactive créée avec Highchartts
Merci. En fait, je résiste à ma fin. A éloigné le code horaire et a itéré le tableau et comparé aux éléments correspondant aux statistiques que je cherchais.
J'ai utilisé le code Furas et j'ai fait une version pour saisir des données de différents pays.
import requests from bs4 import BeautifulSoup import json import pyjsparser import js2xml def scrape(country): url = 'https://www.worldometers.info/coronavirus/country/' + country + '/' soup = BeautifulSoup(requests.get(url).text, "html.parser") scripts = soup.find_all('script') counter = 0 retlist = [ ] retlist.append(country); while counter < len(scripts): try: if js2xml.parse(scripts[counter].string).xpath('//property[@name="title"]//string/text()')[0] in ['Total Cases', 'Active Cases', 'Total Deaths']: retlist.append(js2xml.parse(scripts[counter].string).xpath('//property[@name="title"]//string/text()')[0]) retlist = retlist + json.loads('[' + scripts[counter].string.split('data: [', 1)[1].split(']', 1)[0] + ']') except: pass counter = counter + 1 return retlist countries = ['us', 'spain', 'italy', 'france', 'germany', 'iran', 'china', 'uk', 'south-korea'] for country in countries: print(scrape(country))
Vous devez gratter des données si vous ne pouvez pas facilement trouver la source de données. Voici le référentiel de données qui est durci quotidiennement. github.com/cssegisanddata/covid-19 Cela pourrait vous être plus utile que de gratter des données de une page Web.
Dans HTML, vous pouvez trouver peu de javascripts avec
highchart.chart (....) code> et il y a des données. Il l'envoie directement en HTML.
BTW: Il semble que vous disposiez de ces données comme tableau sur la sous-pompage Worldomètres.info/coronavirus/coronavirus -Death-toll
Est-ce que cela répond à votre question? Puis-je gratter les données brutes de Highcharthart.js? A >
@ user4157124 hier ayush garg met le même lien dans le commentaire ci-dessous sa réponse. Donc, aujourd'hui je l'ai testé et ça marche. Je l'ai mis dans ma réponse :)