Python Panoráma 3: Web Kontroll: hogyan uralkodjunk a Facebook ösztönön?10 perc olvasás

Van az úgy, hogy az ember elkezdi a napját, szépen halad, elvégzi, amit el kell végezni, viszont egyszer csak azon kapja magát, hogy már lassan egy órája nem csinál semmilyen érdemi dolgot csak a Facebook Newsfeed-et görgetgeti, esetleg más közösségi médián szörföl vagy éppen YouTube videókat böngészget. Ez a rész teljesen ideális azoknak, akik gyakran szembesülnek ilyen problémákkal, ugyanis most egy olyan python applikációt fogunk létrehozni, amely képes blokkolni bizonyos előre megadott időintervallumban a kívánt oldalakat. A mostani részben nem csupán a Python-nal, hanem többek között a Task Scheduler-el is meg fogunk ismerkedni.
Köszönet Ardit Sulce-nak a Python kurzusért, amely alapján részben ez a cikk is készült.

CÉL

A célunk tehát egy olyan Python script megírása és megfelelő futtatása, amely képes módosítani, hogy milyen weboldalakhoz férhetünk hozzá a nap adott időszakában. Ebben a részben az lesz az érdekes, hogy nem egy nagy kényelmet nyújtó support könyvtár vagy package “method-függvény hálóba” fogunk hátradőlni nyugodt magabiztossággal, hanem különféle kisebb trükkökkel próbáljuk majd elérni a kívánt hatást.

Amellett, hogy programunk képes lesz letiltani bizonyos időintervallumban weboldalakat, arra is figyelnünk kell, hogy az időintervallumon kívül feloldja a korlátozásokat. Továbbá az is egy elvárás programtól, hogy az futtatható legyen a háttérben és ne jelenjen meg folyton egy Command Line ablak, akárhányszor működésbe lép a programunk. Ha ezek megvannak, akkor nincs is más már hátra, csak hogy Windows-unkon a Task Scheduler-el segítségével ütemezzük a program futtatását, hogy az minden gépindításkor megfelelően elinduljon.

MEGVALÓSÍTÁS

Rögtön vágjunk is akkor bele a lényegbe. Ahhoz, hogy megértsük alkalmazásunk velejét első körben azt kell tisztáznunk, hogy maga a script egy kitüntetett szerepű rendszerfájl köré fog épülni.  Ez a fájl pedig nem más mint a “hosts” fájl, amelynek elérési útvonala a következő: C:\Windows\System32\drivers\etc
Ha megnyitjuk a fájlt, akkor pedig a következőt láthatjuk:

Amennyiben a “hosts” fájlt kiegészítjük a localhost IP címével és a Facebook URL-jével, majd elmentjük, akkor már hiába próbáljuk elérni a Facebook-ot a böngészőnkben, hiszen a “hosts” fájlt úgy módosítottuk, hogy mikor a megadott domain-nel rendelkező oldalakat próbáljuk elérni akkor a 127.0.0.1-re irányít át, ami lényegében a gépünk saját magára mutató címe. Hacsak nem fut egy szerver a gépünkön, akkor a böngészőnk nagy valószínűséggel egy Error-t fog kidobni az oldal felkeresését követően.

previous arrow
next arrow
Shadow
Slider

FONTOS: Mielőtt neki kezdünk programírásnak érdemes a “hosts” fájlról egy másolatot készíteni és áthelyezni abba a mappába, ahol a programunkat is tervezzük írni, hogy először a másolaton tudjuk tesztelni a programunkat. Valamint érdemes a “hosts” fájlról egy backup-ot is készíteni, arra az esetre ha az eredeti “hosts” fájlunk valamilyen okból adódóan mégis megváltozna a programunk hatására.

Tehát akkor a Python scriptünknek ezt a “hosts” fájl másolatot kell módosítania aszerint, hogy mennyi az aktuális idő. Később, mikor már tökéletesítettük a programunkat, alkalmazhatjuk a rendes “hosts” fájlra is. Ahhoz, hogy a programunk képes legyen az aktuális idővel dolgozni szükségünk van a python könyvtárak közül a “time” illetve “datetime” nevűekre. Ezeket importáljuk, majd egy-egy változóban tároljuk el azokat az adatokat, amelyeket később használni fogunk a programkódban. Ezek közé tartozik a “hosts” fájl elérési útvonala, amely a tesztelés időtartama alatt megadható relatívan is, az IP cím, amelyikre vissza akarjuk irányítani a lekérést tehát a 127.0.0.1, valamint azoknak az oldalaknak a domain neve, amelyekre alkalmazni szeretnénk a programot.
Ez eddig így néz ki:

import time
from datetime import datetime as dt

host=r"C:\Windows\System32\drivers\etc\hosts"
redir="127.0.0.1"
website_list=["www.facebook.com", "facebook.com"]

Azonban ha jobban belegondolunk milyen kódra is van szükségünk egy kis nehézségbe ütközünk, mert alapvetően mikor lefuttattunk egy programot, akkor az sorról sorra, fentről lefelé fut le és egy outputot ad ki. Itt azonban arra van szükségünk, hogy a program előre meghatározott folytonossággal megvizsgáljon egy adott feltételt, miszerint az aktuális idő beleesik-e a kritikus tartományba. Ezt a problémát egy while loop segítségével oldhatjuk fel és igazából ezen a while loop-on belül van szükségünk egy feltételes blokkra két elágazással.

Az első ágban azt kell megvizsgálnunk, hogy az aktuális idő beleesik-e a kritikus tartományba. Ennek a vizsgálatára szükségünk van a datetime objektumok használatára, amelyek nem jelentenek mást, mint dátum és idő elemeket, tehát dátumokat, hónapokat, napokat, órákat, perceket és stb. Például a mai dátum hónapját megkaphatom a dt.now().month függvény segítségével. A teszteléshez érdemes print függvényeket is beilleszteni, hogy lássuk, hogy a programunk megfelelően működik-e. Ez valahogy így nézhet ki mondjuk:

import time
from datetime import datetime as dt

host=r"C:\Windows\System32\drivers\etc\hosts"
redir="127.0.0.1"
website_list=["www.facebook.com", "facebook.com"]

while True:
    if dt(dt.now().year,dt.now().month,dt.now().day,8) < dt.now() < dt(dt.now().year,dt.now().month,dt.now().day,16):
        print("Working hours...")
    else:
        print("Free")

Ha lefuttatjuk ezt a programot a Command Line-ban, akkor azt vehetjük észre, hogy a programunk irdatlan sokszor írja ki az outputot. Ez annak köszönhető, hogy ezt a nem nagy számítástechnikai erőforrást igénylő kódot a mai gyors processzorok nagyon gyorsan tudják lefuttatni. Mivel mi egy háttérfolyamatként akarjuk később futtatni ezt a programot, így nem igazán tanácsos feleslegesen sokszor lefuttatni ezt a kódot, hiszen futtatása csökkenő határhasznossággal rendelkezik. Ezt úgy tudjuk kiküszöbölni, hogy a while loop végére egy “time.sleep(5)” sort írunk, amely azt biztosítja, hogy egy lefutás után a program 5 másodpercet alszik, majd újra lefut.

Ahhoz, hogy programunk teljes legyen már csak arra van szükség, hogy a “hosts” fájlt is módosítsa futása közben. Ehhez a kritikus időintervallum esetén a programnak meg kell nyitnia a “hosts” fájlt azt beolvasni, eltárolni egy változóba és megvizsgálni, hogy a website_list elemei benne vannak-e a dokumentumban. Ha igen, akkor programnak nincs további teendője, ha nem, akkor pedig ki kell egészítenie a dokumentumot a fentebb bemutatott módon. Abban az esetben pedig, ha az aktuális idő nem esik a kritikus időtartományba, akkor törölnie kell azokat a sorokat, amelyekben megjelennek a website_list elemei.
Tehát akkor eddig a kód:

import time
from datetime import datetime as dt

host=r"C:\Windows\System32\drivers\etc\hosts"
redir="127.0.0.1"
website_list=["www.facebook.com", "facebook.com"]

while True:
    if dt(dt.now().year,dt.now().month,dt.now().day,8) < dt.now() < dt(dt.now().year,dt.now().month,dt.now().day,16):
        print("Working hours...")
        with open(host,"r+") as file: #the + sign is for the appending capabilities
            content=file.read()
            for website in website_list:
                if website in content:
                    pass
                else:
                    file.write(redir+" "+website+"\n")
    else:
        print("Free")
        with open(host,"r+") as file:
            content=file.readlines()
            file.seek(0)
            for line in content:
                if not any(website in line for website in website_list):
                    file.write(line)
            file.truncate()
    time.sleep(5)

A törlés menete elég trükkös, ugyanis úgy törli a program a sorokat, hogy újraírja az elejétől kezdve (ehhez szükséges a “file.seek(0)”) azokat a sorokat, amelyekben nem találhatók a website_list elemei az utána következő sorokat pedig törli. Ezekután már csak az van hátra, hogy a scriptet átnevezzük “program.py”-ról “program.pyw”-re. Így a programunk már futtatható a háttérben, azonban még egy dologra figyelnünk kell. Mivel a “hosts” fájl egy rendszerfájl, így annak módosításához a legmagasabb fokú jogosultságok szükségesek. Ez azt jelenti, hogy ahhoz, hogy a programunk minden probléma nélkül el tudjon indulni, azt rendszergazdaként kell futtatnunk.

Végül pedig nézzük meg, hogyan tudjuk a scriptünket a Task Scheduler-el úgy ütemezni, hogy az minden gépindításkor elinduljon. Nyissuk meg a Task Scheduler-t, majd hozzunk létre egy új task-et és pipáljuk ki azt a lehetőséget, hogy a legmagasabb jogosultságok mellett induljon el a folyamat. Ezután lépjünk át a “Triggers” fülre és válasszuk ki, hogy a gépindításkor induljon el a folyamatunk. Következő lépésként menjünk át az “Actions” fülre és határozzuk meg a futtatandó programunk helyét. Végül pedig a “Conditions” fülön szedjük ki a pipát a Power-nél, hogy a folyamat akkor is végbemenjen mikor gépünk az akkumulátort használja.

previous arrow
next arrow
Slider

TOVÁBBFEJLESZTÉS ÉS FELHASZNÁLHATÓSÁG

A programunk igazából már most is szolidan megáll a talpán, mint egy hasznos kis alkalmazás, de esetleg még ki lehetne bővíteni egy csinos UI-vel, amely képes tájékoztatni azokat a felhasználókat például, akik nem tudnak az általunk írt program létezéséről és nem értik, miért nem tudják elérni az adott oldalakat. A felhasználás kapcsán pedig a teljesítménynövelés, a szülői felügyelet és különböző szabályzatokból származó alkalmazásokra (például géptermi vizsgáztatás) gondolhatunk.
A kész alkalmazást innen tudod letölteni.

Köszönöm, hogy végigolvastad a posztomat és ha érdekesnek találtad, akkor nézz bele a sorozat többi részébe is.

Gulácsy Dominik

About Dominik Gulácsy

Sophomore at Corvinus University of Budapest studying International Business who is motivated to use relevant academic knowledge to solve problems through optimisation. Dedicated to fully support the development of new business solutions in close collaboration with team members by IoT and data science applications. Gained experience in SQL and VBA but looking forward to learning more. A keen supporter of the circular economy.

View all posts by Dominik Gulácsy →

Leave a Reply

Your email address will not be published. Required fields are marked *