Овај текст сам први пут написао 2021, са примером на огласима за посао са Stack Overflow-а. Тај део сајта је у међувремену угашен, а променио се и Selenium, па стари код више није радио. Зато је пример написан изнова и проверен у октобру 2026. године.
Када је скидање података дозвољено?
Скидање података штеди сате преписивања. Најчешће се користи за:
- праћење цена код добављача или конкуренције;
- пренос сопствених података са старог сајта на нови, када стари систем нема извоз;
- скупљање јавних података за анализу и истраживање;
- проверу сопственог сајта, на пример наслова и линкова на свим страницама.
То што је нешто јавно видљиво не значи да сме да се узме и користи како год желите. Пре него што почнете, проверите:
- robots.txt. На адреси сајта са додатком
/robots.txtвласник наводи које делове сајта роботи не би требало да отварају. - Услове коришћења сајта. Многи сајтови аутоматско преузимање изричито забрањују.
- Ауторска права. Туђе текстове, описе и слике не преносите на свој сајт. То није дозвољено, а не помаже ни у претрази, јер Google дупликате филтрира. Више о томе прочитајте у тексту о дуплираном садржају.
- Личне податке. Имена, адресе е-поште и бројеви телефона су лични подаци и за њих важи закон о заштити података о личности.
- Оптерећење сервера. Правите паузе између захтева, као у примерима испод. Програм који отвара стотине страница у секунди може да обори мали сајт.
- Да ли постоји API. Ако сајт нуди API за податке који вам требају, користите њега. Брже је, поузданије и дозвољено.
Припрема
Пример је рађен на Windows-у, а исти код ради и на Линуксу и macOS-у.
- Инсталирајте Python са python.org. На првом екрану инсталације укључите опцију Add python.exe to PATH, па нема потребе да путању додајете ручно.
- Код пишем у програму Висуал Студио Цоде (visualstudio.com), уз додатак за Python (ms-python.python), који ће вам VS Code сам понудити.
- Направите фолдер за пројекат, отворите га у 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 и BeautifulSoup | Selenium и 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 или базу, уз поштовање правила сајтова са којих раде.
Оставите одговор