Kako skinuti detalje sa web stranice: Python primer korak po korak

Skidanje podataka sa web stranica (web scraping) znači da program umesto vas otvara stranice i iz njih prepisuje ono što vam treba: nazive, cene, adrese, naslove. Ovde je proveren primer u Pythonu, na dva načina: jednostavnim čitanjem stranice i upravljanjem pravim pregledačem, za stranice koje sadržaj prave JavaScriptom. Rezultat se snima u CSV fajl koji se otvara u Excelu.

Ovaj tekst sam prvi put napisao 2021, sa primerom na oglasima za posao sa Stack Overflow-a. Taj deo sajta je u međuvremenu ugašen, a promenio se i Selenium, pa stari kod više nije radio. Zato je primer napisan iznova i proveren u oktobru 2026. godine.

Kada je skidanje podataka dozvoljeno?

Skidanje podataka štedi sate prepisivanja. Najčešće se koristi za:

  • praćenje cena kod dobavljača ili konkurencije;
  • prenos sopstvenih podataka sa starog sajta na novi, kada stari sistem nema izvoz;
  • skupljanje javnih podataka za analizu i istraživanje;
  • proveru sopstvenog sajta, na primer naslova i linkova na svim stranicama.

To što je nešto javno vidljivo ne znači da sme da se uzme i koristi kako god želite. Pre nego što počnete, proverite:

  • robots.txt. Na adresi sajta sa dodatkom /robots.txt vlasnik navodi koje delove sajta roboti ne bi trebalo da otvaraju.
  • Uslove korišćenja sajta. Mnogi sajtovi automatsko preuzimanje izričito zabranjuju.
  • Autorska prava. Tuđe tekstove, opise i slike ne prenosite na svoj sajt. To nije dozvoljeno, a ne pomaže ni u pretrazi, jer Google duplikate filtrira. Više o tome pročitajte u tekstu o dupliranom sadržaju.
  • Lične podatke. Imena, adrese e-pošte i brojevi telefona su lični podaci i za njih važi zakon o zaštiti podataka o ličnosti.
  • Opterećenje servera. Pravite pauze između zahteva, kao u primerima ispod. Program koji otvara stotine stranica u sekundi može da obori mali sajt.
  • Da li postoji API. Ako sajt nudi API za podatke koji vam trebaju, koristite njega. Brže je, pouzdanije i dozvoljeno.

Priprema

Primer je rađen na Windowsu, a isti kod radi i na Linuksu i macOS-u.

  1. Instalirajte Python sa python.org. Na prvom ekranu instalacije uključite opciju Add python.exe to PATH, pa nema potrebe da putanju dodajete ručno.
  2. Kod pišem u programu Visual Studio Code (visualstudio.com), uz dodatak za Python (ms-python.python), koji će vam VS Code sam ponuditi.
  3. Napravite folder za projekat, otvorite ga u VS Code-u, pa u terminalu instalirajte biblioteke:
pip install requests beautifulsoup4 selenium

Komanda pip preuzima biblioteke koje ne dolaze uz Python, pa ne morate da ih tražite po internetu. Za drugi način treba vam i instaliran Firefox. Ranije je trebalo ručno preuzeti geckodriver.exe i kopirati ga u folder projekta, a od verzije 4.6 Selenium to radi sam.

Za vežbu koristimo sajt quotes.toscrape.com, napravljen baš za učenje skidanja podataka. Na njemu je 100 poznatih citata na 10 stranica, a postoji i verzija čiji sadržaj pravi JavaScript. Cilj je da sve citate i njihove autore prebacimo u jednu tabelu.

Koji način izabrati?

Otvorite stranicu u pregledaču i pritisnite Ctrl+U da vidite njen izvorni kod. Ako se podaci koji vam trebaju vide u izvornom kodu, dovoljan je prvi način. Ako ih nema, stranicu dopunjuje JavaScript posle učitavanja, i tada vam treba drugi način.

requests i BeautifulSoupSelenium i Firefox
Kako radiPreuzme HTML stranice i čita gaUpravlja pravim pregledačem, kao da vi klikćete
BrzinaBrzSporiji, jer se stranica zaista prikazuje
JavaScript straniceNe vidi sadržaj koji pravi JavaScriptVidi sve što vidi i korisnik
Prijava, klikovi, formulariTežeLako
Kada ga koristitiUvek kada možeKada prvi način ne vidi podatke

Prvi način: requests i BeautifulSoup

U folderu projekta napravite fajl citati.py sa sledećim kodom:

import csv
import random
import time
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

wait_from = 2
wait_to = 4

url = "https://quotes.toscrape.com/"
headers = {"User-Agent": "Mozilla/5.0 (primer sa programiranje.co.rs)"}

with open("citati.csv", "w", newline="", encoding="utf-8-sig") as csv_file:
    writer = csv.writer(csv_file)
    writer.writerow(["citat", "autor"])

    while url:
        response = requests.get(url, headers=headers, timeout=30)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, "html.parser")

        for quote in soup.select("div.quote"):
            text = quote.select_one("span.text").get_text(strip=True)
            author = quote.select_one("small.author").get_text(strip=True)
            writer.writerow([text, author])

        next_link = soup.select_one("li.next > a")
        url = urljoin(url, next_link["href"]) if next_link else None

        if url:
            time.sleep(random.randint(wait_from, wait_to))

print("Gotovo!")

Pokrenite ga komandom python citati.py. Za tridesetak sekundi u folderu će se pojaviti citati.csv sa 100 citata. Evo šta radi koji deo:

  • wait_from i wait_to određuju koliko sekundi program čeka između dve stranice, svaki put nasumično. Ne želimo da otvaramo stranice prebrzo, jer to opterećuje server, a sajt može i da nas blokira.
  • requests.get preuzima HTML stranice. timeout sprečava da program zauvek čeka sajt koji ne odgovara, a raise_for_status() prekida rad ako sajt vrati grešku, umesto da tiho snimi praznu tabelu.
  • soup.select("div.quote") pronalazi sve elemente po CSS selektoru. Selektor saznate tako što na stranici desnim klikom izaberete Inspect (Pregledaj element) i pogledate u kom elementu i sa kojom klasom je podatak. Ovde je svaki citat u div elementu sa klasom quote, tekst u span.text, a autor u small.author.
  • li.next > a je link „Next“ na dnu stranice. Dok on postoji, program prelazi na sledeću stranicu. Kada ga nema, stigli smo do poslednje stranice i petlja se završava. Funkcija urljoin od relativne adrese linka (/page/2/) pravi punu adresu.

Drugi način: Selenium i Firefox

Verzija sajta na adresi /js/ izgleda isto, ali citate ubacuje JavaScript. U njenom izvornom kodu citata nema, pa prvi način tu vraća praznu tabelu. Selenium otvara pravi Firefox, čeka da se stranica prikaže i klikće na „Next“, isto kao čovek:

import csv
import random
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

wait_from = 2
wait_to = 4

browser = webdriver.Firefox()
browser.get("https://quotes.toscrape.com/js/")
wait = WebDriverWait(browser, 10)

with open("citati-js.csv", "w", newline="", encoding="utf-8-sig") as csv_file:
    writer = csv.writer(csv_file)
    writer.writerow(["citat", "autor"])

    while True:
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.quote")))

        for quote in browser.find_elements(By.CSS_SELECTOR, "div.quote"):
            text = quote.find_element(By.CSS_SELECTOR, "span.text").text
            author = quote.find_element(By.CSS_SELECTOR, "small.author").text
            writer.writerow([text, author])

        next_links = browser.find_elements(By.CSS_SELECTOR, "li.next > a")
        if not next_links:
            break

        time.sleep(random.randint(wait_from, wait_to))
        first_quote = browser.find_element(By.CSS_SELECTOR, "div.quote")
        next_links[0].click()
        wait.until(EC.staleness_of(first_quote))

browser.quit()
print("Gotovo!")
  • webdriver.Firefox() otvara novi prozor Firefoxa kojim program upravlja. Na kraju ga browser.quit() zatvara.
  • find_elements(By.CSS_SELECTOR, ...) je današnji način pretrage. U Seleniumu 3 pisalo se find_elements_by_css_selector(...), i to je bio kod u prvoj verziji ovog teksta. Selenium 4 je te funkcije uklonio, pa stari primeri sa interneta javljaju grešku.
  • WebDriverWait čeka najviše 10 sekundi da se citati pojave na stranici. To je pouzdanije od fiksnog čekanja, jer ne zavisi od brzine sajta.
  • staleness_of(first_quote) posle klika čeka da stara stranica nestane. Bez toga bi program mogao dva puta da pročita istu stranicu, pre nego što se nova učita.

Ako ne želite da gledate prozor pregledača, Firefox može da radi i nevidljivo. Umesto browser = webdriver.Firefox() napišite:

options = webdriver.FirefoxOptions()
options.add_argument("-headless")
browser = webdriver.Firefox(options=options)

Kako otvoriti rezultat u Excelu?

Oba primera snimaju CSV fajl sa kodiranjem utf-8-sig. Taj dodatak na početku fajla kaže Excelu da je tekst u UTF-8, pa se slova kao što su č, ć i đ prikazuju ispravno. Modul csv sam stavlja navodnike oko teksta koji sadrži zarez, pa citati ostaju u jednoj ćeliji.

Ako vam Excel ceo red stavi u jednu kolonu, to je zbog regionalnih podešavanja: kod nas Excel kao razdelnik očekuje tačku-zarez. Tada otvorite fajl preko Data → From Text/CSV, ili u kodu napišite csv.writer(csv_file, delimiter=";").

Česti problemi

  • AttributeError: 'WebDriver' object has no attribute 'find_elements_by_css_selector': kod je pisan za Selenium 3. Zamenite ga oblikom find_elements(By.CSS_SELECTOR, ...) kao u primeru iznad.
  • Tabela je prazna: stranica sadržaj pravi JavaScriptom, pa koristite Selenium, ili se promenio CSS selektor. Proverite ga ponovo preko Inspect.
  • Greška 403 ili 429: sajt vas je blokirao ili traži da usporite. Povećajte pauze i proverite da li sajt uopšte dozvoljava automatsko preuzimanje.
  • UnicodeEncodeError na Windowsu: fajl je otvoren bez encoding. Uvek navedite encoding="utf-8" ili "utf-8-sig".
  • Program je radio, a sada ne radi: sajt je promenio izgled i selektori više ne odgovaraju. Programe za skidanje podataka treba održavati, jer sajtovi ne pitaju pre nego što se promene.

Da li je lako skinuti podatke sa web stranice?

Sa malo koda jeste, kao što se vidi iz primera. U ovom primeru je korišćen Python, ali isto može da se uradi i u PHP-u, C#-u i drugim programskim jezicima. Teži deo počinje kod pravih sajtova: prijava, zaštita od robota, česte promene izgleda. Takve projekte sam radio za klijente, a primere možete pogledati u portfelju, pod automatizacija pregledača i web scraping.

Nadam se da vam je uputstvo pomoglo. Ako zapne negde, ostavite komentar ispod i pomoći ću.

Treba vam program koji ovo radi umesto vas?

Pravim programe koji sami prikupljaju podatke sa sajtova, popunjavaju formulare i prebacuju podatke u Excel ili bazu, uz poštovanje pravila sajtova sa kojih rade.