Skip to content
DA-07-10-25-lesson3
[
{"id":258368918,
"doc_vob":"1",
"doc_vob_name":null,
"doc_number":"2563",
"doc_date":"2023-06-09",
"doc_v_date":"2023-06-09",
"trans_date":"2023-06-0",
"amount":84,
"amount_cop":8400,
"currency":"UAH"
,"payer_edrpou":"34978804",
"payer_name":"КАМ\"ЯНСЬКИЙ ВДВС ЦМУМЮ(М.КИЇВ)",
"payer_account":"UA428201720355209001000700482",
"payer_mfo":null,"payer_bank":null,
"payer_edrpou_fact":null,
"payer_name_fact":null,
"recipt_edrpou":"37930566",
"recipt_name":"ГУК у Черк.обл./тг м. Кам'янка/2207000",
"recipt_account":"UA228999980333279305000023631",
"recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"*;147;xxxx;; xxxx; №696/317/21; 29.07.xxxx; Табурець ТГ; №xxxx; Виконавчий збір",
"doc_add_attr":null,
"region_id":23,
"payment_type":
"nsep",
"payment_data":null,
"source_id":2,
"source_name":"ДКСУ",
"kekv":null,"kpk":"0000000",
"contractId":null,
"contractNumber":null,
"budgetCode":"9900000000",
"system_key":null,
"system_key_ff":null
},
{"id":258368919,"doc_vob":"1","doc_vob_name":null,"doc_number":"45","doc_date":"2023-06-08","doc_v_date":"2023-06-08","trans_date":"2023-06-10","amount":4567.05,
"amount_cop":456705,"currency":"UAH","payer_edrpou":"25496858","payer_name":"Мазурівський аграрний центр ПТО","payer_account":"UA868201720344221013200010315","payer_mfo":null,"payer_bank":null,"payer_edrpou_fact":null,"payer_name_fact":null,"recipt_edrpou":"25510334","recipt_name":"АТ \"Вiнницяобленерго\" СО \"Могилiв-Подi","recipt_account":"UA683052990000026000006104839","recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"0611091:2240;оплата зг.договору №44 вiд 07.06.2023р. за технiчне обслуговування обладнання;акт 2300063003 вiд 07.06.2023р.;ПДВ-761,17;;","doc_add_attr":null,"region_id":2,"payment_type":"nsep","payment_data":null,"source_id":2,"source_name":"ДКСУ","kekv":2240,"kpk":"0611091","contractId":null,"contractNumber":null,"budgetCode":"0210000000","system_key":null,"system_key_ff":null},{"id":258368920,"doc_vob":"1","doc_vob_name":null,"doc_number":"133","doc_date":"2023-06-09","doc_v_date":"2023-06-09","trans_date":"2023-06-10","amount":555.46,"amount_cop":55546,"currency":"UAH","payer_edrpou":"23918835","payer_name":"Центр НСП Золочівської селищної ради","payer_account":"UA548201720344280006000052864","payer_mfo":null,"payer_bank":null,"payer_edrpou_fact":null,"payer_name_fact":null,"recipt_edrpou":"21560766","recipt_name":"АТ \"Укртелеком\" Харкiв фiлiя","recipt_account":"UA093808050000000026007734849","recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"0813241;2240;опл. за телекомунiкацiйнi послуги за травень 2023 р.;дог.№641839 вiд 22.02.2018 р.;рах.-акт№ 5.2023.631015 вiд 31.05.2023р.;в т.ч. ПДВ-92,58грн.","doc_add_attr":null,"region_id":20,"payment_type":"nsep","payment_data":null,"source_id":2,"source_name":"ДКСУ","kekv":2240,"kpk":"0813241","contractId":null,"contractNumber":null,"budgetCode":"2050800000","system_key":null,"system_key_ff":null},{"id":258368922,"doc_vob":"1","doc_vob_name":null,"doc_number":"1768","doc_date":"2023-06-07","doc_v_date":"2023-06-08","trans_date":"2023-06-10","amount":210,"amount_cop":21000,"currency":"UAH","payer_edrpou":"36892614","payer_name":"КЗ\"ЛМЦБС\"","payer_account":"UA348201720344240001000063542","payer_mfo":null,"payer_bank":null,"payer_edrpou_fact":null,"payer_name_fact":null,"recipt_edrpou":"xxxxxxxxxx","recipt_name":"ФОП Нікітін С.П.","recipt_account":"UA713052990000026007040807946","recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"1014030;2210;за матеріали для ремонтних робіт господарськ.способом (шакран боковий);накл.№255 від 06.06.23, дог№53/ЦБ/23 від 06.06.23;Без ПДВ.","doc_add_attr":null,"region_id":3,"payment_type":"nsep","payment_data":null,"source_id":2,"source_name":"ДКСУ","kekv":2210,"kpk":"1014030","contractId":null,"contractNumber":null,"budgetCode":"0355100000","system_key":null,"system_key_ff":null},{"id":258368923,"doc_vob":"1","doc_vob_name":null,"doc_number":"178","doc_date":"2023-06-08","doc_v_date":"2023-06-08","trans_date":"2023-06-10","amount":37000,"amount_cop":3700000,"currency":"UAH","payer_edrpou":"21661316","payer_name":"НАМ України","payer_account":"UA568201720343180001000012162","payer_mfo":null,"payer_bank":null,"payer_edrpou_fact":null,"payer_name_fact":null,"recipt_edrpou":"37993783","recipt_name":"ГУК у м.Києвi/Шевченк.р-н/11010100","recipt_account":"UA778999980333149340000026011","recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"*;101; ;21661316;код 11010100;КПКВ 6571020;КЕКВ 2111;податок на доходи з фiзосiб з вiдпускних i з/п за 1пол.06.2023р.","doc_add_attr":null,"region_id":26,"payment_type":"nsep","payment_data":null,"source_id":2,"source_name":"ДКСУ","kekv":2111,"kpk":"6571020","contractId":null,"contractNumber":null,"budgetCode":"9900000000","system_key":null,"system_key_ff":null},{"id":258369203,"doc_vob":"1","doc_vob_name":null,"doc_number":"18665","doc_date":"2023-06-08","doc_v_date":"2023-06-08","trans_date":"2023-06-10","amount":3200,"amount_cop":320000,"currency":"UAH","payer_edrpou":"34721466","payer_name":"СОКАЛЬСЬКИЙ РАЙОННИЙ ВІДДІЛ ДЕРЖАВНОЇ","payer_account":"UA428201720355279001000700959","payer_mfo":null,"payer_bank":null,"payer_edrpou_fact":null,"payer_name_fact":null,"recipt_edrpou":"xxxxxxxxxx","recipt_name":"Яремко Валентина Вікторівна","recipt_account":"UA043052990000026204733614090","recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"аліменти№ 601/xxxx/16; 25.05.xxxx; Яремко ЯВ; №xxxx; Кошти за ВД, стягнуті на користь стягувача","doc_add_attr":null,"region_id":13,"payment_type":"nsep","payment_data":null,"source_id":2,"source_name":"ДКСУ","kekv":null,"kpk":"0000000","contractId":null,"contractNumber":null,"budgetCode":"9900000000","system_key":null,"system_key_ff":null},{"id":258369204,"doc_vob":"1","doc_vob_name":null,"doc_number":"387","doc_date":"2023-06-09","doc_v_date":"2023-06-10","trans_date":"2023-06-10","amount":11971.24,"amount_cop":1197124,"currency":"UAH","payer_edrpou":"03188501","payer_name":"Тетерівський дитячий буд.-інтернат","payer_account":"UA288201720344250001000032013","payer_mfo":null,"payer_bank":null,"payer_edrpou_fact":null,"payer_name_fact":null,"recipt_edrpou":"44096781","recipt_name":"ГУ ДПС у Житомирськiй обл.","recipt_account":"UA078999980000355659201020630","recipt_mfo":null,"recipt_bank":null,"recipt_edrpou_fact":null,"recipt_name_fact":null,"payment_details":"*;101;03188501;КПКВК 0813101 КЕКВ 2120 ЄСВ-22% нарахування на вiдпускнi за червень 2023р..;;;","doc_add_attr":null,"region_id":6,"payment_type":"nsep","payment_data":null,"source_id":2,"source_name":"ДКСУ","kekv":2120,"kpk":"0813101","contractId":null,"contractNumber":null,"budgetCode":"0610000000","system_key":null,"system_key_ff":null},{"id":258369205,"doc_vob":"1","doc_vob_name":null,"doc_number":"7","doc_date":"2023-06-08","doc_v_date":"2023-06-10","trans_date":"2023-06-10","amount":470.34,"amount_cop":47034,"currency":"UAH","payer_edrpou":"02143229","payer_name":"Управління освіти і науки міської ради","payer_account":"UA198201720344270024085040126","payer_mfo":nDataCamp Blog Scraper
🎯 Призначення
Python скрипт для автоматичного збору статей з блогу DataCamp (datacamp.com/blog).
🔧 Основні функції
1. scrape_datacamp_alternative() — RSS парсинг
scrape_datacamp_alternative() — RSS парсинг- Метод: Завантаження RSS feed (https://www.datacamp.com/blog/rss.xml)
- Переваги: Найнадійніший, офіційний спосіб
- Дані: Заголовок, URL, опис, дата публікації
- Результат: DataFrame з 4 колонками
2. scrape_datacamp_working() — HTML парсинг
scrape_datacamp_working() — HTML парсинг- Метод: 3 послідовні стратегії пошуку
- Метод 1: Пошук
<article>тегів - Метод 2: Пошук
<div>з класами (post, card, item) - Метод 3: Загальний пошук посилань
/blog/
- Метод 1: Пошук
- Переваги: Fallback якщо RSS недоступний
- Дані: Заголовок, URL
- Результат: DataFrame з 2 колонками
3. main() — Головний orchestrator
main() — Головний orchestrator- Пробує спочатку RSS (найкращий метод)
- Якщо RSS fails → переходить на HTML парсинг
- Зберігає результати в CSV файли
- Виводить статистику та перші 5 статей
📦 Технології
- requests — HTTP запити
- BeautifulSoup4 — HTML/XML парсинг
- pandas — обробка даних
- lxml — XML parser для RSS
import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
import json
def scrape_datacamp_working():
"""
Робоча версія парсера DataCamp Blog
"""
url = "https://www.datacamp.com/blog"
# Більш реалістичні headers
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Cache-Control': 'max-age=0'
}
try:
print("🔍 Відправляємо запит до DataCamp Blog...")
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
print(f"✅ Отримано відповідь: {response.status_code}")
print(f"📄 Розмір сторінки: {len(response.text)} символів")
soup = BeautifulSoup(response.text, 'html.parser')
articles = []
# Метод 1: Шукаємо article tags
article_tags = soup.find_all('article')
print(f"🔎 Знайдено <article> тегів: {len(article_tags)}")
for article in article_tags:
# Шукаємо заголовок
title_tag = article.find(['h2', 'h3', 'h4'], class_=lambda x: x and ('title' in x.lower() or 'heading' in x.lower()))
if not title_tag:
title_tag = article.find(['h2', 'h3', 'h4'])
# Шукаємо посилання
link_tag = article.find('a', href=True)
if title_tag and link_tag:
title = title_tag.get_text(strip=True)
url = link_tag.get('href')
# Формуємо повний URL якщо потрібно
if url.startswith('/'):
url = f"https://www.datacamp.com{url}"
if len(title) > 10 and '/blog/' in url:
articles.append({
'title': title,
'url': url
})
# Метод 2: Якщо article tags не спрацювали, шукаємо div з класами
if len(articles) == 0:
print("⚠️ Article tags не знайдено, пробуємо інший підхід...")
# Шукаємо всі div з можливими класами блогу
blog_items = soup.find_all('div', class_=lambda x: x and any(
keyword in x.lower() for keyword in ['post', 'card', 'item', 'article']
))
print(f"🔎 Знайдено blog items: {len(blog_items)}")
for item in blog_items:
link = item.find('a', href=True)
if link and '/blog/' in link.get('href'):
title_elem = item.find(['h2', 'h3', 'h4', 'h5'])
if title_elem:
title = title_elem.get_text(strip=True)
url = link.get('href')
if url.startswith('/'):
url = f"https://www.datacamp.com{url}"
if len(title) > 10:
articles.append({
'title': title,
'url': url
})
# Метод 3: Шукаємо всі посилання які ведуть на /blog/
if len(articles) == 0:
print("⚠️ Пробуємо загальний пошук посилань...")
all_links = soup.find_all('a', href=lambda x: x and '/blog/' in x and x.count('/') >= 3)
print(f"🔎 Знайдено посилань на блог: {len(all_links)}")
seen_urls = set()
for link in all_links:
url = link.get('href')
if url.startswith('/'):
url = f"https://www.datacamp.com{url}"
# Уникаємо дублікатів
if url in seen_urls:
continue
seen_urls.add(url)
# Шукаємо заголовок
title = link.get_text(strip=True)
# Якщо текст посилання занадто короткий, шукаємо батьківський елемент
if len(title) < 10:
parent = link.find_parent(['div', 'article', 'section'])
if parent:
title_tag = parent.find(['h2', 'h3', 'h4', 'h5'])
if title_tag:
title = title_tag.get_text(strip=True)
if len(title) > 10 and len(title) < 200:
articles.append({
'title': title,
'url': url
})
# Видаляємо дублікати
unique_articles = []
seen_urls = set()
for article in articles:
if article['url'] not in seen_urls:
seen_urls.add(article['url'])
unique_articles.append(article)
print(f"\n✅ Знайдено унікальних статей: {len(unique_articles)}")
return pd.DataFrame(unique_articles)
except requests.exceptions.RequestException as e:
print(f"❌ Помилка при запиті: {e}")
return pd.DataFrame()
except Exception as e:
print(f"❌ Несподівана помилка: {e}")
return pd.DataFrame()
def scrape_datacamp_alternative():
"""
Альтернативний метод: парсинг через API або RSS
"""
# DataCamp має RSS feed
rss_url = "https://www.datacamp.com/blog/rss.xml"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
try:
print("🔍 Пробуємо завантажити RSS feed...")
response = requests.get(rss_url, headers=headers, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'xml')
articles = []
items = soup.find_all('item')
print(f"✅ Знайдено статей в RSS: {len(items)}")
for item in items:
title = item.find('title').get_text(strip=True) if item.find('title') else 'No title'
link = item.find('link').get_text(strip=True) if item.find('link') else ''
description = item.find('description').get_text(strip=True) if item.find('description') else ''
pub_date = item.find('pubDate').get_text(strip=True) if item.find('pubDate') else ''
articles.append({
'title': title,
'url': link,
'description': description,
'published': pub_date
})
return pd.DataFrame(articles)
except Exception as e:
print(f"❌ Помилка при завантаженні RSS: {e}")
return pd.DataFrame()
def main():
"""
Головна функція
"""
print("=" * 60)
print("📰 DataCamp Blog Scraper")
print("=" * 60)
# Спочатку пробуємо RSS (найбільш надійний метод)
print("\n🔄 Метод 1: RSS Feed")
print("-" * 60)
df_rss = scrape_datacamp_alternative()
if len(df_rss) > 0:
print(f"\n✅ RSS успішно! Зібрано {len(df_rss)} статей")
df_rss.to_csv('datacamp_articles_rss.csv', index=False, encoding='utf-8')
print("💾 Збережено в: datacamp_articles_rss.csv")
print("\n📋 Перші 5 статей:")
print(df_rss.head())
return
# Якщо RSS не спрацював, пробуємо HTML парсинг
print("\n🔄 Метод 2: HTML Parsing")
print("-" * 60)
df_html = scrape_datacamp_working()
if len(df_html) > 0:
print(f"\n✅ HTML парсинг успішний! Зібрано {len(df_html)} статей")
df_html.to_csv('datacamp_articles_html.csv', index=False, encoding='utf-8')
print("💾 Збережено в: datacamp_articles_html.csv")
print("\n📋 Перші 5 статей:")
print(df_html.head())
else:
print("\n❌ Не вдалося зібрати дані жодним методом")
print("\n💡 Можливі причини:")
print(" 1. Сайт блокує скрапінг")
print(" 2. Змінилась структура HTML")
print(" 3. Потрібен JavaScript для завантаження контенту")
print("\n🔧 Рекомендації:")
print(" - Використайте Selenium для dynamic контенту")
print(" - Перевірте robots.txt: https://www.datacamp.com/robots.txt")
print(" - Розгляньте використання офіційного API (якщо доступний)")
if __name__ == "__main__":
main()import requests
from bs4 import BeautifulSoup
import pandas as pd
import time
def scrape_datacamp_simple():
"""Проста версія для демонстрації"""
url = "https://www.datacamp.com/blog"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
articles = []
# Знаходимо всі посилання на статті
links = soup.find_all('a', href=True)
for link in links:
href = link.get('href')
if '/blog/' in href and href.count('/') > 3:
title = link.get_text(strip=True)
if len(title) > 10:
articles.append({
'title': title,
'url': href
})
return pd.DataFrame(articles)
# Збір даних
df = scrape_datacamp_simple()
df.to_csv('datacamp_articles.csv', index=False)
print(f"Зібрано {len(df)} статей")