Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: GloGlo 29. 06. 2022, 22:57:10

Název: Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 29. 06. 2022, 22:57:10
Zdravím. Chtěl bych se zeptat, jaký je nejrychlejší a nejednodušší headless browser s Javascriptem. Jde mi o webscrawling.

Momentálně používám headless Chrome přes Selenium, nedělám nic složitýho, ale žere to hrozně moc CPU. (Mám jich spuštěných několik současně).

Potřebuju, aby to umělo Javascript a hlavně fungovalo přes Python, Javu vůbec neumím.

Pokoušel sem se několik hodin rozjet Htmlunit přes selenium-server, ale za živýho boha sem nepřišel na to, jak to udělat.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: APhacker_mob 29. 06. 2022, 23:12:57
Pyppeteer
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 30. 06. 2022, 00:54:46
Pyppeteer

Opravdu je to rychlejší než Selenium + Chrome? O hodně?
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 30. 06. 2022, 01:06:33
Pyppeteer

Opravdu je to rychlejší než Selenium + Chrome? O hodně?

v headless modu nejspis ano.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 30. 06. 2022, 01:15:09
Mám jich spuštěných několik současně.

nekolik instanci pythonu nebo nekolik browseru? Ani jedno podle me neni treba, z jednoho skriptu jde otevrit nekolik url najednou v jednom browseru.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 30. 06. 2022, 05:46:00
Pyppeteer

Opravdu je to rychlejší než Selenium + Chrome? O hodně?

v headless modu nejspis ano.

Díval sem se na to, problém je v tom, že to používá asyncio, který neumím :D

Tak sem se ho jakože začal učit, ale je to pro mě dost těžký :D Potřebuju otevřít několik tabů a neustále v nich checkovat zdroják.. Ty taby s požadovanou stránkou sem otevřel, to tak těžký nebylo.. ale aby to permanentně checkovalo zdroják, jak sem pochopil, tak asi nějak musím propojit asyncio + threading a to teda zatím nedávám :D

Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: panpanika 30. 06. 2022, 08:00:15
zrovna nedavno tu na asyncio vysly super clanky p tisnovskeho. (na druhou stranu on snad ani neumi napsat spatny clanek na cokoliv :) )
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 30. 06. 2022, 10:21:07
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 30. 06. 2022, 15:16:20
zrovna nedavno tu na asyncio vysly super clanky p tisnovskeho. (na druhou stranu on snad ani neumi napsat spatny clanek na cokoliv :) )

Nevím, jestli sem špatně hledal, ale články byly spíš o threading a o asyncio je jen menší část jednoho z nich - https://www.root.cz/clanky/soubezne-a-paralelne-bezici-ulohy-naprogramovane-v-pythonu-2/#k09
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 30. 06. 2022, 16:37:25
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil

Můžu se zeptat, jak bys udělal, aby to současně parsovalo třeba pět stránek současně bez použití threading?

Nějak pomocí asyncio.Queue? Jakože jedna stránka bude hotová, pošle signál (nebo jak se tomu říká) další a takhle prostě budou postupovat postupně kolem dokola?

Když sem vytvořil 5 tasks přes asyncio.create_task(), tak to parsovalo jen 1 stránku a ostatní měly smůlu. Jedině když sem udělal parse(data) a následně time.sleep(X), tak to po skončení funkce parse(data) skončilo na další task.




Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Ink 30. 06. 2022, 18:08:14
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil

Můžu se zeptat, jak bys udělal, aby to současně parsovalo třeba pět stránek současně bez použití threading?

Nějak pomocí asyncio.Queue? Jakože jedna stránka bude hotová, pošle signál (nebo jak se tomu říká) další a takhle prostě budou postupovat postupně kolem dokola?

Když sem vytvořil 5 tasks přes asyncio.create_task(), tak to parsovalo jen 1 stránku a ostatní měly smůlu. Jedině když sem udělal parse(data) a následně time.sleep(X), tak to po skončení funkce parse(data) skončilo na další task.

Hele a Google Ti nefunguje? https://stackoverflow.com/questions/28492103/how-to-combine-python-asyncio-with-threads
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 30. 06. 2022, 18:59:21
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil

Můžu se zeptat, jak bys udělal, aby to současně parsovalo třeba pět stránek současně bez použití threading?

Nějak pomocí asyncio.Queue? Jakože jedna stránka bude hotová, pošle signál (nebo jak se tomu říká) další a takhle prostě budou postupovat postupně kolem dokola?

Když sem vytvořil 5 tasks přes asyncio.create_task(), tak to parsovalo jen 1 stránku a ostatní měly smůlu. Jedině když sem udělal parse(data) a následně time.sleep(X), tak to po skončení funkce parse(data) skončilo na další task.

Hele a Google Ti nefunguje? https://stackoverflow.com/questions/28492103/how-to-combine-python-asyncio-with-threads

on tohle nepotrebuje, to se pouziva, kdyz potrebujes v asyncio aplikaci blokujici volani. pyppeteer je plne neblokujici.

to co chce (vic tabu v jednom browseru) by slo i pomoci selenia a vlaken
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 30. 06. 2022, 19:41:52
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil

Můžu se zeptat, jak bys udělal, aby to současně parsovalo třeba pět stránek současně bez použití threading?

Nějak pomocí asyncio.Queue? Jakože jedna stránka bude hotová, pošle signál (nebo jak se tomu říká) další a takhle prostě budou postupovat postupně kolem dokola?

Když sem vytvořil 5 tasks přes asyncio.create_task(), tak to parsovalo jen 1 stránku a ostatní měly smůlu. Jedině když sem udělal parse(data) a následně time.sleep(X), tak to po skončení funkce parse(data) skončilo na další task.

priklad

Kód: [Vybrat]
import asyncio
from pyppeteer import launch


async def get_title(browser, url):
    page = await browser.newPage()
    await page.goto(url)
    return await page.title()


async def get_titles(*urls):
    browser = await launch()
    titles = await asyncio.gather(
        *[asyncio.create_task(get_title(browser, url)) for url in urls]
    )
    await browser.close()
    return titles


print(asyncio.run(get_titles("https://example.com", "https://google.com")))

vypise ['Example Domain', 'Google']
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 01:13:17
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil

Můžu se zeptat, jak bys udělal, aby to současně parsovalo třeba pět stránek současně bez použití threading?

Nějak pomocí asyncio.Queue? Jakože jedna stránka bude hotová, pošle signál (nebo jak se tomu říká) další a takhle prostě budou postupovat postupně kolem dokola?

Když sem vytvořil 5 tasks přes asyncio.create_task(), tak to parsovalo jen 1 stránku a ostatní měly smůlu. Jedině když sem udělal parse(data) a následně time.sleep(X), tak to po skončení funkce parse(data) skončilo na další task.

Hele a Google Ti nefunguje? https://stackoverflow.com/questions/28492103/how-to-combine-python-asyncio-with-threads

Google mi samozřejmě funguje a taky než sem položil otázku, tak sem zabil docela hodně času pokusem přijít na to sám. Ale tuhle konkrétní věc sem prostě nikde kloudně nenašel no.

Btw až po docela dlouhý době sem se pak někde dočetl, že threading/concurrent.futures/asyncio ty souběhy/konkurenci řeší vlastně všechny a že je blbost ty metody kombinovat, jen to prej přináší problémy.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 01:13:52
jak sem pochopil, tak asi nějak musím propojit asyncio + threading

nepochopil

Můžu se zeptat, jak bys udělal, aby to současně parsovalo třeba pět stránek současně bez použití threading?

Nějak pomocí asyncio.Queue? Jakože jedna stránka bude hotová, pošle signál (nebo jak se tomu říká) další a takhle prostě budou postupovat postupně kolem dokola?

Když sem vytvořil 5 tasks přes asyncio.create_task(), tak to parsovalo jen 1 stránku a ostatní měly smůlu. Jedině když sem udělal parse(data) a následně time.sleep(X), tak to po skončení funkce parse(data) skončilo na další task.

priklad

Kód: [Vybrat]
import asyncio
from pyppeteer import launch


async def get_title(browser, url):
    page = await browser.newPage()
    await page.goto(url)
    return await page.title()


async def get_titles(*urls):
    browser = await launch()
    titles = await asyncio.gather(
        *[asyncio.create_task(get_title(browser, url)) for url in urls]
    )
    await browser.close()
    return titles


print(asyncio.run(get_titles("https://example.com", "https://google.com")))

vypise ['Example Domain', 'Google']

diky moc!
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 05:40:13
A.P.Hacker:

Předělal sem teda svůj parsovací skript, aby místo selenium používal pyppeteer. Na notebooku mi to funguje dobře.. jenže když ten stejnej kod nahraju na VPS a pokouším se ho spustit, tak se to prostě zasekne u vytvoření stránky

Kód: [Vybrat]
page = await browser.newPage()
... a pak to prostě čeká a nic nedělá.. dokud to nevypnu... Absolutně nechápu proč. Pyppeteer mám samozřejmě nainstalovanej a taky mám stáhlý chrome přes pyppeteer-install.

Celej kod:

Kód: [Vybrat]
import asyncio
from pyppeteer import launch
import datetime
from bs4 import BeautifulSoup
from DB import *

sports = {}
sports['soccer'] = 'https://www.somewebsite.com'
sports['tennis'] = 'https://www.somewebsite.com'

async def AddToDB(data):
# saves any changes to DB
pass

async def parse(data, soup, sport):
# does something
return data

async def CheckPage(browser, sport):
data = {}
url = sports[sport]
page = await browser.newPage()
        print (page) # nikdy se nevytiskne
await page.goto(url)

while True:
content = await page.content()
soup = BeautifulSoup(content, 'html.parser')
data = await parse(data, soup, sport)
asyncio.sleep(1)

async def main():
print ("Started: " + datetime.datetime.now().strftime('%H:%M:%S'))
browser = await launch ({ "headless": True, "args": ["--start-maximized"]})

return await asyncio.gather(
       *[asyncio.create_task(CheckPage(browser, sport)) for sport in sports]
)


asyncio.run (main())


Nějakej nápad?
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Ink 01. 07. 2022, 07:42:52
Btw až po docela dlouhý době sem se pak někde dočetl, že threading/concurrent.futures/asyncio ty souběhy/konkurenci řeší vlastně všechny a že je blbost ty metody kombinovat, jen to prej přináší problémy.

Nevím, jestli rozumím, co máš přesně na mysli. Ale asyncio, by default, přece dělá kooperativní multitasking, to znamená, že pokud v daném tasku něco počítáš a ve frontě už máš další práci, musí další task čekat, to znamená, že se připravuješ o výkon. asyncio, threading a multiprocessing prostě dělají každý něco jiného a nejsou takhle jednoduše zastupitelné. Mrkni třeba sem:

https://realpython.com/python-concurrency/
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 11:55:03
hm k tomu výše.. vypadá to na bug v Pyppeteeru :///

https://github.com/pyppeteer/pyppeteer/issues/395

Tímto se pro mě bohužel pyppeteer stává nepoužitelným
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: jano6 01. 07. 2022, 13:10:43
Tak tu máme v tom evidentne poriadny hokej.

Táto slučka vyzerá na prvý pohľad ako problém:

Kód: [Vybrat]
while True:
content = await page.content()
soup = BeautifulSoup(content, 'html.parser')
data = await parse(data, soup, sport)
asyncio.sleep(1)

Vytvárať vlastné slučky pomocou while True je big, big no.
Asynchrónne programovanie je založené na slučke udalostí, ktorú však vytvorí
asyncio modul.

Citace
asyncio.run function runs the passed coroutine, taking care of managing the
asyncio event loop and finalizing asynchronous generators.

Takmer určite tvoj problém nespôsobil Puppeteer, ale chyba v tvojom programe.

Mne prijde, že sa snažíš vytvoriť pravdepodobne nejaký monitorovací skript.
Ak je to tak, tak si najpr treba vytvoriť skript, ktorý vykoná požadovaný task
a až potom neskôr riešiť monitoring.

Add puppeteer. Headless browser použiješ vtedy, ak sa potrebuješ dostať
za JS bránu, napr. za prihlasovacie okno. Pre ostatné prípady sa bežne
používajú http clienty. Python má httpx, ktorý zvládne aj async programy.

Kód: [Vybrat]
#!/usr/bin/python

import httpx
import asyncio
from bs4 import BeautifulSoup

async def get_async(url):
    async with httpx.AsyncClient() as client:
        return await client.get(url)

urls = ['http://webcode.me', 'https://httpbin.org',
    'https://something.com', 'https://stackoverflow.com',
    'https://github.com']

async def launch():
    resps = await asyncio.gather(*map(get_async, urls))
    data = [resp.text for resp in resps]

    for content in data:
       soup = BeautifulSoup(content, 'lxml')
       print(soup.title)

asyncio.run(launch())

Príklad asynchrónne stiahne HTML kód z viacerých stránok, a výpíše ich
titulky.

Čo je ale vlastne tvoja požiadavka, o čo sa snažíš? Pojem webscrawling
neexistuje, máme web scraping a web crawling. Web scraping je sťahovanie dát
z internetu, trebárs ceny leteniek k danému dňu. Web crawling je to, čo robí
Google.

Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 01. 07. 2022, 13:44:11
Ten kod se zasekne tak jako tak, na te nekonecne smycce.

volani asyncio.sleep bez await na nic neceka.

tezko rict proc to ze serveru nejde, muze souviset s blacklistovanymi serverovymi IP adresami.

Pokud jsi je zahltil requesty generovanymi tou nekonecnou smyckou bez cekani, je dobra sance, ze te zablokovali.

Ten tazatel na GH to spousti z nejake CI sluzby, tam je take dost velka sance blokace.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: Google CTCCTCGGCGGGCACGTAG 01. 07. 2022, 13:58:37
Add puppeteer. Headless browser použiješ vtedy, ak sa potrebuješ dostať
za JS bránu, napr. za prihlasovacie okno. Pre ostatné prípady sa bežne
používajú http clienty. Python má httpx, ktorý zvládne aj async programy.

casto je samotny obsah generovany javascriptem, ruzne tabulky tahane ajaxem a podobne.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 15:52:07
Ten kod se zasekne tak jako tak, na te nekonecne smycce.

volani asyncio.sleep bez await na nic neceka.

tezko rict proc to ze serveru nejde, muze souviset s blacklistovanymi serverovymi IP adresami.

Pokud jsi je zahltil requesty generovanymi tou nekonecnou smyckou bez cekani, je dobra sance, ze te zablokovali.

Ten tazatel na GH to spousti z nejake CI sluzby, tam je take dost velka sance blokace.

Ne, chyba nebyla v tom, že by nebyl dostupný nějaký určitý web, ale nešlo mi vůbec v pyppeteeru otevřít nový tab. Zaseklo se to už na await browser.newPage(). Nicméně nakonec sem vyřešil pomocí minimal args:

Kód: [Vybrat]
minimal_args = [
'--autoplay-policy=user-gesture-required',
'--disable-background-networking',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-breakpad',
'--disable-client-side-phishing-detection',
'--disable-component-update',
'--disable-default-apps',
'--disable-dev-shm-usage',
'--disable-domain-reliability',
'--disable-features=AudioServiceOutOfProcess',
'--disable-hang-monitor',
'--disable-ipc-flooding-protection',
'--disable-notifications',
'--disable-offer-store-unmasked-wallet-cards',
'--disable-popup-blocking',
'--disable-print-preview',
'--disable-prompt-on-repost',
'--disable-renderer-backgrounding',
'--disable-setuid-sandbox',
'--disable-speech-api',
'--disable-sync',
'--hide-scrollbars',
'--ignore-gpu-blacklist',
'--metrics-recording-only',
'--mute-audio',
'--no-default-browser-check',
'--no-first-run',
'--no-pings',
'--no-sandbox',
'--no-zygote',
'--password-store=basic',
'--use-gl=swiftshader',
'--use-mock-keychain',
'--allow-insecure-localhost',
];

teď mi to na serveru funguje.

Ale teda musím říct, že moje představy, že to takhle bude rychlejší, se absolutně, absolutně vůbec nenaplnily.

Doteď sem používal selenium, jeden tab a prostě rychle za sebou otevíral, checkoval, zavíral stránky.. Ale otevřenej byl vždycky jen jeden tab. Program top mi ukazoval více spuštěnejch procesů chrome, jak kdy, zhruba 5-7 jich bylo, a load average kolísal kolem 3-6.

Jenže teďka, když teda používám ten pyppeteer, jeden spuštěnej browser a 7 otevřenejch tabů, jejichž zdroják checkuju... Spuštěnejch procesů chrome je nějak o dost víc, asi 15-20, a load average je zhruba 3x vyšší.. resp. kolísá cca mezi 10-20.. ale chvilku byl i 50, lol..
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 16:02:10
Tak tu máme v tom evidentne poriadny hokej.

Táto slučka vyzerá na prvý pohľad ako problém:

Kód: [Vybrat]
while True:
content = await page.content()
soup = BeautifulSoup(content, 'html.parser')
data = await parse(data, soup, sport)
asyncio.sleep(1)

Vytvárať vlastné slučky pomocou while True je big, big no.
Asynchrónne programovanie je založené na slučke udalostí, ktorú však vytvorí
asyncio modul.

Citace
asyncio.run function runs the passed coroutine, taking care of managing the
asyncio event loop and finalizing asynchronous generators.

Takmer určite tvoj problém nespôsobil Puppeteer, ale chyba v tvojom programe.

Mne prijde, že sa snažíš vytvoriť pravdepodobne nejaký monitorovací skript.
Ak je to tak, tak si najpr treba vytvoriť skript, ktorý vykoná požadovaný task
a až potom neskôr riešiť monitoring.

Add puppeteer. Headless browser použiješ vtedy, ak sa potrebuješ dostať
za JS bránu, napr. za prihlasovacie okno. Pre ostatné prípady sa bežne
používajú http clienty. Python má httpx, ktorý zvládne aj async programy.

Kód: [Vybrat]
#!/usr/bin/python

import httpx
import asyncio
from bs4 import BeautifulSoup

async def get_async(url):
    async with httpx.AsyncClient() as client:
        return await client.get(url)

urls = ['http://webcode.me', 'https://httpbin.org',
    'https://something.com', 'https://stackoverflow.com',
    'https://github.com']

async def launch():
    resps = await asyncio.gather(*map(get_async, urls))
    data = [resp.text for resp in resps]

    for content in data:
       soup = BeautifulSoup(content, 'lxml')
       print(soup.title)

asyncio.run(launch())

Príklad asynchrónne stiahne HTML kód z viacerých stránok, a výpíše ich
titulky.

Čo je ale vlastne tvoja požiadavka, o čo sa snažíš? Pojem webscrawling
neexistuje, máme web scraping a web crawling. Web scraping je sťahovanie dát
z internetu, trebárs ceny leteniek k danému dňu. Web crawling je to, čo robí
Google.

OK. Web scraping. Web s datama, který se v prohlížeči aktualizujou skoro každou sekundu nějak pomocí Ajaxu/JS. Kdybych stáhnul stránku pomocí wget/curl, tak je to nepoužitelná statická stránka bez těch dat. Takže potřebuju mít spuštěnej prohlížeč, který předává zdroják parsovacímu skriptu, který ho projede, podívá se na změny od posledního checku a pokud nějaký jsou, tak to uloží do databáze.

Data v budoucnu chci zpracovávat pomocí AI. (Až se to líp naučím)
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: GloGlo 01. 07. 2022, 16:08:02
Jo, jinak v tom mém kodu mělo být
Kód: [Vybrat]
await asyncio.sleep(1) a ne jen
Citace
asyncio.sleep(1)
, ale na to sem přišel rychle, protože mi to dávalo warning.
Název: Re:Nejrychlejší a nejjednodušší headless browser na Python?
Přispěvatel: APhacker_mob 01. 07. 2022, 17:44:59
Jenže teďka, když teda používám ten pyppeteer, jeden spuštěnej browser a 7 otevřenejch tabů, jejichž zdroják checkuju... Spuštěnejch procesů chrome je nějak o dost víc, asi 15-20, a load average je zhruba 3x vyšší.. resp. kolísá cca mezi 10-20.. ale chvilku byl i 50, lol..

Zkusil bych ty stranky zavirat pomoci page.close