Guten Tag zusammen,
ich beschäftige mich zur Zeit mit Python und finde die Sprache sehr intuitiv.
Im Moment möchte ich eine Tabelle mit Erdbebendaten aus
https://en.vedur.is/earthquakes-and-vol ... view=table
scrapen, die ich als Trainingsdaten nutzen will, um andere Anwendungen (z.B. R) damit zu nutzen.
Ich komme mit requests und BeautifulSoup schon etwas weiter, habe aber im Moment keinen "Anpacker" um an Daten der auf o.g. Seite sichtbaren Datentabelle zugreifen zu können.
Die in den verschieden verschachtelten div-Tags sichtbaren Hinweise <div id="qtable" class="qtable"> bekomme ich nicht 'gefasst".
Ich bitte um Hinweise, welcher Tag hier der richtige "Anfasser" ist.
Anmerkung: in einem script-Tag auf der Seite steht die komplette Liste der Messwerte zwar unschön aber erkennbar drin. Wie könnte ich alternativ daran kommen?
Ich danke für Hinweise.
Tom
Mein bisheriges Script:
import requests
from bs4 import BeautifulSoup
#python C:\tmp\python\scripts\basicscrape.py
url = 'https://en.vedur.is/earthquakes-and-vol ... view=table'
res = requests.get(url)
html_page = res.content
soup = BeautifulSoup(html_page, 'html.parser')
text = soup.find_all(text=True)
output = ''
blacklist = [
'[document]',
'noscript',
'header',
'html',
'meta',
'head',
'body',
'input',
# there may be more elements you don't want, such as "style", etc.
]
for t in text:
if t.parent.name not in blacklist:
output += '{} '.format(t)
print(output)
Web-Scraping einer HTML-Tabelle, unklare div-/bzw class Tags
- __blackjack__
- User
- Beiträge: 14054
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@tomrause: Die Daten stehen nicht in der Tabelle sondern in einem <script>-Tag als JavaScript. Da kommt man beispielsweise heran in dem man das JavaScript ausführt. Es gibt einen (langsamen) Interpreter in Python mit dem das ginge:
Code: Alles auswählen
#!/usr/bin/env python3
import re
import bs4
import js2py
import requests
from glom import glom, T
from rich import print
URL = (
"https://en.vedur.is/earthquakes-and-volcanism/earthquakes"
"/reykjanespeninsula/"
)
def main():
response = requests.get(URL)
response.raise_for_status()
soup = bs4.BeautifulSoup(response.content, "html.parser")
js_source = soup.find(
"script", src=False, text=re.compile(r"\s+var VI;")
).text
context = js2py.EvalJs()
context.execute(js_source)
quake_info = glom(
context.VI.quakeInfo,
[
{
"timestamp": T["t"].toJSON(),
"latitude": "lat",
"longitude": "lon",
"depth": "dep",
"magnitude": "s",
"quality": "q",
"distance": "dL",
"direction": "dD",
"location_name": "dR",
}
],
)
print(quake_info)
if __name__ == "__main__":
main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Guten Morgen __blackjack__ und erst einmal vielen Dank für deine Antwort.
Ich habe deinen Code übernommen und zuerst mittels pip install js2py ... /...glom und ... / ...rich nachinstalliert (Was diese Module genau mache lese ich mir im Anschluß durch)
Leider tritt ein Fehler beim Ausführen auf: VI sei nicht definiert.
Noch was: du schriebst:
Dennoch tauchen im Quelltext der Seite sauber formatierte Tabellen-markups mit den Werten auf...., übersetzt der Browser zur Laufzeit aus dem Script in die Tabelle? Ich bin verwirrt und bitte um weitere Hinweise.
Vielen Dank
Tom
Ich habe deinen Code übernommen und zuerst mittels pip install js2py ... /...glom und ... / ...rich nachinstalliert (Was diese Module genau mache lese ich mir im Anschluß durch)
Leider tritt ein Fehler beim Ausführen auf: VI sei nicht definiert.
- Beim definieren von js_source setzt du re ein. Kann es sein, daß dort VI fälschlicherweise ausgeschlossen wird, so daß bei quake_info VI.quakeInfo nicht erkannt wird?
- Habe ich mir möglicherweise eine nicht passende glom-Version installiert (wenn es die überhaupt gibt...)?
- Ich benutze Python 3.9.1.
Noch was: du schriebst:
.Die Daten stehen nicht in der Tabelle sondern in einem <script>-Tag als JavaScript
Dennoch tauchen im Quelltext der Seite sauber formatierte Tabellen-markups mit den Werten auf...., übersetzt der Browser zur Laufzeit aus dem Script in die Tabelle? Ich bin verwirrt und bitte um weitere Hinweise.
Vielen Dank
Tom
Code: Alles auswählen
C:\Users\TR>python c:\tmp\python\scripts\readjstopy.py
Traceback (most recent call last):
File "c:\tmp\python\scripts\readjstopy.py", line 46, in <module>
main()
File "c:\tmp\python\scripts\readjstopy.py", line 27, in main
context.VI.quakeInfo,
File "C:\Users\TR\AppData\Roaming\Python\Python39\site-packages\js2py\evaljs.py", line 242, in __getattr__
return getattr(self._var, var)
File "C:\Users\TR\AppData\Roaming\Python\Python39\site-packages\js2py\base.py", line 1214, in __getattr__
cand = to_python(self._obj.get(str(item)))
File "C:\Users\TR\AppData\Roaming\Python\Python39\site-packages\js2py\base.py", line 1158, in get
raise MakeError('ReferenceError', '%s is not defined' % prop)
js2py.internals.simplex.JsException: ReferenceError: VI is not defined
Ich bitte um Hinweise
Danke
Tom
Danke
Tom
- __blackjack__
- User
- Beiträge: 14054
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@tomrause: Meh, im aktuellen BeautifulSoup4 gibt es kein `Tag.text`-Attribut mehr, das heisst jetzt `string`. Diese Änderung steht nicht in der Dokumentation. 
Also aus dem:
wird:
Dann sollte es auch mit der neuesten BS4-Version funktionieren.
Edit: Eine Tabelle mit den formatierten Werten taucht eben *nicht* im Quelltext der Seite auf. Im gesamten Quelltext der Seite kommt nicht ein einziges <table>-Element vor. Das wird alles zur Laufzeit im Browser per JavaScript erzeugt.
Also aus dem:
Code: Alles auswählen
js_source = soup.find(
"script", src=False, text=re.compile(r"\s+var VI;")
).text
Code: Alles auswählen
js_source = soup.find(
"script", src=False, string=re.compile(r"\s+var VI;")
).string
Edit: Eine Tabelle mit den formatierten Werten taucht eben *nicht* im Quelltext der Seite auf. Im gesamten Quelltext der Seite kommt nicht ein einziges <table>-Element vor. Das wird alles zur Laufzeit im Browser per JavaScript erzeugt.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari