michi1983
Goto Top

Python requests-html library

Liebe Admins,

ich spiele mich gerade etwas mit der Python Library 'requests-html'.

Was ich möchte
Eine Website aufrufen, dann ein JavaScript ausführen um dann eine Info zu crawlen die erst dann ersichtlich wird, wenn ich eben z.B. auf einen Knopf gedrückt habe.

Mein Test
from requests_html import HTMLSession

# create html session
s = HTMLSession()

# define url to fetch
url = 'https://administrator.de'  

# fetch url
r = s.get(url)

# get HTML of website
html = r.html

# prepare JavaScript to pass after loading the website
script = """  
    () => {
        const button = document.querySelector('#button-ticker');  
        if(button) {
            button.click()
        }
    }
"""  

# render website and pass javascript
html.render()

print(html.find('title')[0].text)  

Wenn ich den oben angegebenen Code ausführe, dann erhalte ich den korrekten Titel der Website zurück:
IT-Wissen, Forum und Community - Administrator

Jetzt soll es laut Dokumentation auch möglich sein, beim rendern ein Script mitzugeben.

Dann würde sich genau eine Zeile Code bei mir ändern, nämlich Zeile 26:
html.render(script=script)

Ich würde mir dann eigentlich diesen Titel hier erwarten:
Ticker - Administrator

Zumindest kann ich das verifzieren wenn ich in der Entwicklerconsole einfach:
document.title
eingebe. Einmal auf der Startseite und einmal nachdem ich auf Ticker geklickt habe.

Was ich allerdings erhalte ist folgende Fehlermeldung, sobald ich das Script mitgebe beim Rendern:
Traceback (most recent call last):
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/execution_context.py", line 105, in evaluateHandle  
    'userGesture': True,  
pyppeteer.errors.NetworkError: Protocol error (Runtime.callFunctionOn): Cannot find context with specified id

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/mlu/playground/admin/administrator.py", line 26, in <module>  
    html.render(script=script)
  File "/home/mlu/.local/lib/python3.7/site-packages/requests_html.py", line 598, in render  
    content, result, page = self.session.loop.run_until_complete(self._async_render(url=self.url, script=script, sleep=sleep, wait=wait, content=self.html, reload=reload, scrolldown=scrolldown, timeout=timeout, keep_page=keep_page))
  File "/usr/lib64/python3.7/asyncio/base_events.py", line 587, in run_until_complete  
    return future.result()
  File "/home/mlu/.local/lib/python3.7/site-packages/requests_html.py", line 531, in _async_render  
    content = await page.content()
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/page.py", line 761, in content  
    return await frame.content()
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/frame_manager.py", line 393, in content  
    '''.strip())  
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/frame_manager.py", line 309, in evaluate  
    pageFunction, *args, force_expr=force_expr)
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/execution_context.py", line 54, in evaluate  
    pageFunction, *args, force_expr=force_expr)
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/execution_context.py", line 108, in evaluateHandle  
    _rewriteError(e)
  File "/home/mlu/.local/lib/python3.7/site-packages/pyppeteer/execution_context.py", line 237, in _rewriteError  
    raise type(error)(msg)
pyppeteer.errors.NetworkError: Execution context was destroyed, most likely because of a navigation.

Kennt sich hier jemand mit der Library aus?

Was übersehe ich?

Danke und Gruß
Michi

Content-ID: 7091031773

Url: https://administrator.de/contentid/7091031773

Ausgedruckt am: 24.11.2024 um 10:11 Uhr

7010350221
Lösung 7010350221 10.05.2023 aktualisiert um 12:07:16 Uhr
Goto Top
Hi
Du musst etwas warten bis der Browser die neue Seite geladen ist (Render-Parameter "sleep"), sonst versuchst du im html-object eine Abfrage auszuführen obwohl der Browser die Seite noch nicht fertig geladen hat, deswegen auch die Fehlermeldung:
Execution context was destroyed, most likely because of a navigation..
#!/usr/bin/python3
from requests_html import HTMLSession
s = HTMLSession()
url = 'https://administrator.de'  
r = s.get(url)
myscript = '''  
    () => {
	    document.querySelector('#button-ticker').click();  
    }
'''  
r.html.render(script=myscript,sleep=2)
print(r.html.find('title')[0].text)  
s.close()
Gruß
michi1983
michi1983 10.05.2023 um 12:16:31 Uhr
Goto Top
Vielen Dank! Ich habe es mit wait versucht, hat aber nicht geklappt, warum es mit sleep klappt, verstehe ich war nicht, aber du hast mir gerade den Tag gerettet! face-smile
7010350221
Lösung 7010350221 10.05.2023 aktualisiert um 12:19:42 Uhr
Goto Top
Zitat von @michi1983:

Vielen Dank! Ich habe es mit wait versucht, hat aber nicht geklappt, warum es mit sleep klappt, verstehe ich war nicht,

Kann ich dir erklären warum wait hier nicht funktioniert hat:
wait – The number of seconds to wait before loading the page, preventing timeouts (optional).
sleep – Integer, if provided, of how many seconds to sleep after initial render.
https://requests.readthedocs.io/projects/requests-html/en/latest/
michi1983
michi1983 10.05.2023 um 12:21:23 Uhr
Goto Top
Ach herrje, verstehen sollte man das manual halt auch...
Danke dir!
7010350221
7010350221 10.05.2023 aktualisiert um 12:25:15 Uhr
Goto Top
Man muss nur immer im Hinterkopf haben das bei der virtuellen Browserautomation über die Selenium-Bibliothek immer eine unsichtbare Browser-Instanz läuft die eben agiert wie ein echter Browser nur eben ohne Fenster face-smile.