Web Scraping’as su Python

Categories PhytonPosted on

Turiu pasidaręs Excel failiuką, kuriame kaupiu info apie iš EPN (dabar vadinasi Backit) puslapio gautus centus. Kas keletą dienų užeinu ir iš puslapyje esančios lentelės nusikopijuoju įrašus ir įpeistinu į savo excelį. Tas kiek pabosta, todėl vienas iš dalykų, kuriuos norėjau išmokti su Pitonu, tai web sraping’as – t.y. būdas automatiškai nusikopijuoti informaciją iš tinklalapių. Taigi, pasėdėjau geros pusantros dienos ir štai kas pavyko.

Srapingas šiaip labai palengvina gyvenimą. Bet kai kurie tinklalapiai nemėgsta tokių dalykų ir turi visokių captcha prisidiegę, tai šito apeiti nepavyks. Mano atveju captcha nėra, tai iš šitos pusės pasisekė. Bet pats tinklalapis gan dažnai gliūčina ir neužkrauna reikiamos lentelės, reikia parefrešinti, kad ji atsirastų.

Taigi pirmiausia pradėjau nuo bibliotekų.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import pandas as pd
from bs4 import BeautifulSoup
import re
import os
import time
import datetime
driver = webdriver.Chrome(r"C:\Users\Justinas\Documents\Python Scripts\chromedriver.exe")

Čia jų gal ir nereikalingų yra, bet ilgai bandžiau išgauti normą rezultatą ir jau dabar nebežinau kurių nereikia :). Čia yra reikalingas naršyklės draiveris. Aš naudojau chrome draiverį, jį galima parsisiųsti iš čia.

driver.get("https://backit.me/en/cashback/friends/statistics")

Panaudodami draiverį atidarom savo norimą puslapį. Paleidus šitą scripto dalį, realiai atsidaro tinklalapis chrome lange ir jame galima matyti kas vyksta.

driver.find_element_by_id("loginEmailInput").send_keys("***@*****")
driver.find_element_by_id ("loginPassInput").send_keys("*********")
driver.find_element_by_id("loginSubmit").click()

Norint žinoti kokius elementus nurodyti, reikia atsidaryti puslapio šaltinį ir paieškoti:

Jei nesigaus, rašykit į komentarus, galėsiu detaliau aprašyti. O ten kode žvaigždučių vietose reikia įrašyti prisijungimo duomenis.

Prie tinklalapio prisiloginti naudojama Selenium biblioteka, o informacijos nulupimui BeautifulSoup:

soup_level1=BeautifulSoup(driver.page_source, 'html')

Šita skripto dalis randa lentelės duomenis html kode ir juos surenka.

htmltable = soup_level1.find('table', { 'class' : 'table table-income' })
def tableDataText(table):       
    rows = []
    trs = table.find_all('tr')
    headerow = [td.get_text(strip=True) for td in trs[0].find_all('th')] 
    if headerow: 
        rows.append(headerow)
        trs = trs[1:]
    for tr in trs:
        rows.append([td.get_text(strip=True) for td in tr.find_all('td')])
    return rows

Ir kai jau juos turime tvarkingus, galime galime formuoti savo lentelę:

list_table = tableDataText(htmltable)
list_table[:2]
driver.close()

Čia taip pat dar uždaryti chrome draiverį reikia. Kad būtų patogiau dirbti esamą lentelę įkėliau į pandų dataframe:

dftable = pd.DataFrame(list_table[1:], columns=list_table[0])
dftable.rename(columns ={"Date":"DATE","On hold":"REVENUE ON HOLD","Revenue":"REVENUE" },inplace = True)
dftable=dftable[dftable['DATE'].str.contains("Total")== False]

Iš EPN nuskaitytos lentelės apačioje atsidūrė „Total“ eilutė, tai dar ją teko nufiltruoti.

Tolimesnis mano tikslas buvo prisidėti čia jau esamą excel lentelę. Tiesiog norėjau, kad šitas skriptas pildytų jau esamus duomenis naujais.

df_epn = pd.read_excel (r"C:\Users\Justinas\OneDrive\_Pajamos\EPN.xlsx", sheet_name="Reff")
df_epn2 = pd.read_excel (r"C:\Users\Justinas\OneDrive\_Pajamos\EPN.xlsx", sheet_name="Cashback")

Esamas failas turi du sheet’us – „Reff“ ir „Cashback“. Juos reikia čia užsikelti abu ir paskui abu įrašyti į naują failą. Nes kiekvieną kartą scriptui prasisukus, šitas failas būtų ne šiaip papildomas naujais įrašais, bet perrašomas iš naujo.

df_bendras=pd.concat([dftable, df_epn])
df_bendras['REVENUE ON HOLD'] = df_bendras['REVENUE ON HOLD'].str.replace('$', '')
df_bendras['DATE'] = pd.to_datetime(df_bendras['DATE'])
df_bendras=df_bendras.groupby('DATE')[['REVENUE ON HOLD','REVENUE']].max()

Pagal planą skriptas prasisukinės kelis kartus per dieną, todėl bus tokių situacijų, kai jau esamame faile ir iš tinklalapio nuskaitytoje lentelėje bus tos pačios dienos įrašų su skirtingomis reikšmėmis. Žodžiu aš visam šitam reikalui panaudojau tokią logiką: sujungiau abi lenteles, ir sugrupavau įrašus pagal datą, o kurie įrašai dubliuojasi, ims tą, kuriame „REVENUE ON HOLD“ bus didesnis (REVENUE visada nuliai būna).

Na ir visa magija baigta. Beliko tik viską eksportuoti atgal į excel:

with pd.ExcelWriter(r'C:\Users\Justinas\Desktop\test.xlsx') as ew:
    df_bendras.to_excel(ew, sheet_name="Reff",index=True)
    df_epn2.to_excel(ew, sheet_name="Cashback",index=False)

Čia kodas kitoks nei naudojau praėjusiame įraše, kadangi reikia iš karto įrašyti info į du sheet’us.

Dabar atrodo darbo čia nedaug, bet kol viską išsiaiškinau, tai buvo ką veikt 🙂 Tolimesnis mano žingsnis su šituo, bus jį įkelti į RasberryPi, ir paleisti suktis. Ir gal vietoje excel, nukreipti duomenis saugoti į kokią duombazę, į Google Big Query pavyzdžiui.

Parašykite komentarą