Comment extraire ce contenu rendu par javascript?
J'utilise requests_htmlpour extraire l'élément <div id="TranslationsHead">...</div>dans cette URL dans lequel <span id="LangBar"> ... </span>est rendu par javascript.
from requests_html import HTMLSession
session = HTMLSession()
from bs4 import BeautifulSoup
url = 'https://www.thefreedictionary.com/love'
headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'}
r = session.get(url, headers = headers)
soup = BeautifulSoup(r.content, 'html.parser')
soup.select_one('#TranslationsHead')
et son résultat est <div id="TranslationsHead"><span id="TranslationsTitle">Translations</span></div>. Malheureusement, il ne capture toujours pas <span id="LangBar"> ... </span>.
Pourriez-vous s'il vous plaît expliquer comment capturer un tel contenu?
Je vous remercie beaucoup pour votre aide!
Réponses
Vous devez appeler r.html.render()pour afficher la page avec JavaScript:
from requests_html import HTMLSession
url = 'https://www.thefreedictionary.com/love'
session = HTMLSession()
r = session.get(url)
r.html.render()
lang_bar = r.html.find('#LangBar', first=True)
print(lang_bar.html)
Si vous souhaitez embellir la sortie, importez BeautifulSoup et utilisez:
soup = BeautifulSoup(lang_bar.html, 'html.parser')
print(soup.prettify())
Si vous voulez les langues:
for lcd in lang_bar.find('div.lcd'):
print(lcd.text)
Les sorties:
Afrikaans / Afrikaans
Arabic / العربية
Bulgarian / Български
Chinese Simplified / 中文简体
Chinese Traditional / 中文繁體
Croatian / Hrvatski
Czech / Česky
Danish / Dansk
Dutch / Nederlands
Esperanto / Esperanto
Estonian / eesti keel
Farsi / فارسی
Finnish / Suomi
etc
Si vous souhaitez obtenir toutes les traductions, la note esest la valeur par défaut:
from requests_html import HTMLSession
url = 'https://www.thefreedictionary.com/love'
session = HTMLSession()
r = session.get(url)
r.html.render()
for span in r.html.find('span.trans'):
print(span, span.text)
Les sorties:
<Element 'span' class=('trans',) lang='af' style='display: none;'> liefde
<Element 'span' class=('trans',) lang='ar' style='display: none;'> حُب
<Element 'span' class=('trans',) lang='bg' style='display: none;'> любов
<Element 'span' class=('trans',) lang='br' style='display: none;'> amor
<Element 'span' class=('trans',) lang='cs' style='display: none;'> láska
<Element 'span' class=('trans',) lang='de' style='display: none;'> die Liebe
<Element 'span' class=('trans',) lang='da' style='display: none;'> kærlighed
<Element 'span' class=('trans',) lang='el' style='display: none;'> αγάπη
<Element 'span' class=('trans',) lang='es' style='display: inline;'> amor
Si vous souhaitez simuler un clic sur une langue et afficher les résultats:
from requests_html import HTMLSession
url = 'https://www.thefreedictionary.com/love'
session = HTMLSession()
r = session.get(url)
script = """
() => {
if ( document.readyState === "complete" ) {
document.getElementsByClassName("fl_ko")[0].click();
}
}
"""
r.html.render(script=script, timeout=10, sleep=2)
for span in r.html.find('span.trans[style="display: inline;"]'):
print(span, span.text)
Les sorties:
<Element 'span' class=('trans',) lang='ko' style='display: inline;'> 애정
<Element 'span' class=('trans',) lang='ko' style='display: inline;'> 연애
<Element 'span' class=('trans',) lang='ko' style='display: inline;'> 사랑하는 사람
<Element 'span' class=('trans',) lang='ko' style='display: inline;'> (테니스) 영점
<Element 'span' class=('trans',) lang='ko' style='display: inline;'> 사랑하다
MIS À JOUR EN RÉPONSE À UN COMMENTAIRE
Jupyter, Spyder etc. utilisent une boucle d'événements sous le capot et request-html appelle loop.run_until_complete qui lève cette exception lorsque la boucle est déjà en cours d'exécution. Avez-vous essayé d'utiliser AsyncHTMLSession?
from requests_html import AsyncHTMLSession
url = 'https://www.thefreedictionary.com/love'
asession = AsyncHTMLSession()
async def get_results():
r = await asession.get(url)
await r.html.arender()
return r
r = asession.run(get_results)
lang_bar = r[0].html.find('#LangBar', first=True)
print(lang_bar.html)
Ou:
from requests_html import AsyncHTMLSession
url = 'https://www.thefreedictionary.com/love'
asession = AsyncHTMLSession()
script = """
() => {
if ( document.readyState === "complete" ) {
document.getElementsByClassName("fl_ko")[0].click();
}
}
"""
async def get_results():
r = await asession.get(url)
await r.html.arender(script=script, timeout=10, sleep=2)
return r
r = asession.run(get_results)
for span in r[0].html.find('span.trans[style="display: inline;"]'):
print(span, span.text)
from bs4 import BeautifulSoup
from requests_html import HTMLSession
url = 'https://www.thefreedictionary.com/love'
headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0'}
session = HTMLSession()
resp = session.get(url, headers = headers)
resp.html.render()
soup = bs(resp.html.html, "lxml")
soup.find("div", {"id": "TranslationsHead"})