Како скинути детаље са веб странице: Python пример корак по корак

Скидање података са веб страница (web scraping) значи да програм уместо вас отвара странице и из њих преписује оно што вам треба: називе, цене, адресе, наслове. Овде је проверен пример у Python-у, на два начина: једноставним читањем странице и управљањем правим прегледачем, за странице које садржај праве JavaScript-ом. Резултат се снима у CSV фајл који се отвара у Excel-у.

Овај текст сам први пут написао 2021, са примером на огласима за посао са Stack Overflow-а. Тај део сајта је у међувремену угашен, а променио се и Selenium, па стари код више није радио. Зато је пример написан изнова и проверен у октобру 2026. године.

Када је скидање података дозвољено?

Скидање података штеди сате преписивања. Најчешће се користи за:

  • праћење цена код добављача или конкуренције;
  • пренос сопствених података са старог сајта на нови, када стари систем нема извоз;
  • скупљање јавних података за анализу и истраживање;
  • проверу сопственог сајта, на пример наслова и линкова на свим страницама.

То што је нешто јавно видљиво не значи да сме да се узме и користи како год желите. Пре него што почнете, проверите:

  • robots.txt. На адреси сајта са додатком /robots.txt власник наводи које делове сајта роботи не би требало да отварају.
  • Услове коришћења сајта. Многи сајтови аутоматско преузимање изричито забрањују.
  • Ауторска права. Туђе текстове, описе и слике не преносите на свој сајт. То није дозвољено, а не помаже ни у претрази, јер Google дупликате филтрира. Више о томе прочитајте у тексту о дуплираном садржају.
  • Личне податке. Имена, адресе е-поште и бројеви телефона су лични подаци и за њих важи закон о заштити података о личности.
  • Оптерећење сервера. Правите паузе између захтева, као у примерима испод. Програм који отвара стотине страница у секунди може да обори мали сајт.
  • Да ли постоји API. Ако сајт нуди API за податке који вам требају, користите њега. Брже је, поузданије и дозвољено.

Припрема

Пример је рађен на Windows-у, а исти код ради и на Линуксу и macOS-у.

  1. Инсталирајте Python са python.org. На првом екрану инсталације укључите опцију Add python.exe to PATH, па нема потребе да путању додајете ручно.
  2. Код пишем у програму Висуал Студио Цоде (visualstudio.com), уз додатак за Python (ms-python.python), који ће вам VS Code сам понудити.
  3. Направите фолдер за пројекат, отворите га у VS Code-у, па у терминалу инсталирајте библиотеке:
pip install requests beautifulsoup4 selenium

Команда pip преузима библиотеке које не долазе уз Python, па не морате да их тражите по интернету. За други начин треба вам и инсталиран Firefox. Раније је требало ручно преузети geckodriver.exe и копирати га у фолдер пројекта, а од верзије 4.6 Selenium то ради сам.

За вежбу користимо сајт quotes.toscrape.com, направљен баш за учење скидања података. На њему је 100 познатих цитата на 10 страница, а постоји и верзија чији садржај прави JavaScript. Циљ је да све цитате и њихове ауторе пребацимо у једну табелу.

Који начин изабрати?

Отворите страницу у прегледачу и притисните Ctrl+U да видите њен изворни код. Ако се подаци који вам требају виде у изворном коду, довољан је први начин. Ако их нема, страницу допуњује JavaScript после учитавања, и тада вам треба други начин.

requests и BeautifulSoupSelenium и Firefox
Како радиПреузме HTML странице и чита гаУправља правим прегледачем, као да ви кликћете
БрзинаБрзСпорији, јер се страница заиста приказује
JavaScript страницеНе види садржај који прави JavaScriptВиди све што види и корисник
Пријава, кликови, формулариТежеЛако
Када га користитиУвек када можеКада први начин не види податке

Први начин: requests и BeautifulSoup

У фолдеру пројекта направите фајл citati.py са следећим кодом:

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!")

Покрените га командом python citati.py. За тридесетак секунди у фолдеру ће се појавити citati.csv са 100 цитата. Ево шта ради који део:

  • wait_from и wait_to одређују колико секунди програм чека између две странице, сваки пут насумично. Не желимо да отварамо странице пребрзо, јер то оптерећује сервер, а сајт може и да нас блокира.
  • requests.get преузима HTML странице. timeout спречава да програм заувек чека сајт који не одговара, а raise_for_status() прекида рад ако сајт врати грешку, уместо да тихо сними празну табелу.
  • soup.select("div.quote") проналази све елементе по CSS селектору. Селектор сазнате тако што на страници десним кликом изаберете Inspect (Прегледај елемент) и погледате у ком елементу и са којом класом је податак. Овде је сваки цитат у div елементу са класом quote, текст у span.text, а аутор у small.author.
  • li.next > a је линк „Next“ на дну странице. Док он постоји, програм прелази на следећу страницу. Када га нема, стигли смо до последње странице и петља се завршава. Функција urljoin од релативне адресе линка (/page/2/) прави пуну адресу.

Други начин: Selenium и Firefox

Верзија сајта на адреси /js/ изгледа исто, али цитате убацује JavaScript. У њеном изворном коду цитата нема, па први начин ту враћа празну табелу. Selenium отвара прави Firefox, чека да се страница прикаже и кликће на „Next“, исто као човек:

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() отвара нови прозор Firefox-а којим програм управља. На крају га browser.quit() затвара.
  • find_elements(By.CSS_SELECTOR, ...) је данашњи начин претраге. У Selenium-у 3 писало се find_elements_by_css_selector(...), и то је био код у првој верзији овог текста. Selenium 4 је те функције уклонио, па стари примери са интернета јављају грешку.
  • WebDriverWait чека највише 10 секунди да се цитати појаве на страници. То је поузданије од фиксног чекања, јер не зависи од брзине сајта.
  • staleness_of(first_quote) после клика чека да стара страница нестане. Без тога би програм могао два пута да прочита исту страницу, пре него што се нова учита.

Ако не желите да гледате прозор прегледача, Firefox може да ради и невидљиво. Уместо browser = webdriver.Firefox() напишите:

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

Како отворити резултат у Excel-у?

Оба примера снимају CSV фајл са кодирањем utf-8-sig. Тај додатак на почетку фајла каже Excel-у да је текст у UTF-8, па се слова као што су ч, ћ и ђ приказују исправно. Модул csv сам ставља наводнике око текста који садржи зарез, па цитати остају у једној ћелији.

Ако вам Excel цео ред стави у једну колону, то је због регионалних подешавања: код нас Excel као разделник очекује тачку-зарез. Тада отворите фајл преко Data → From Text/CSV, или у коду напишите csv.writer(csv_file, delimiter=";").

Чести проблеми

  • AttributeError: 'WebDriver' object has no attribute 'find_elements_by_css_selector': код је писан за Selenium 3. Замените га обликом find_elements(By.CSS_SELECTOR, ...) као у примеру изнад.
  • Табела је празна: страница садржај прави JavaScript-ом, па користите Selenium, или се променио CSS селектор. Проверите га поново преко Inspect.
  • Грешка 403 или 429: сајт вас је блокирао или тражи да успорите. Повећајте паузе и проверите да ли сајт уопште дозвољава аутоматско преузимање.
  • UnicodeEncodeError на Windows-у: фајл је отворен без encoding. Увек наведите encoding="utf-8" или "utf-8-sig".
  • Програм је радио, а сада не ради: сајт је променио изглед и селектори више не одговарају. Програме за скидање података треба одржавати, јер сајтови не питају пре него што се промене.

Да ли је лако скинути податке са wеб странице?

Са мало кода јесте, као што се види из примера. У овом примеру је коришћен Python, али исто може да се уради и у PHP-у, C#-у и другим програмским језицима. Тежи део почиње код правих сајтова: пријава, заштита од робота, честе промене изгледа. Такве пројекте сам радио за клијенте, а примере можете погледати у портфељу, под аутоматизација прегледача и web scraping.

Надам се да вам је упутство помогло. Ако запне негде, оставите коментар испод и помоћи ћу.

Треба вам програм који ово ради уместо вас?

Правим програме који сами прикупљају податке са сајтова, попуњавају формуларе и пребацују податке у Excel или базу, уз поштовање правила сајтова са којих раде.