Приклад збірки PyQt6 проєкту PyInstaller-ом.
Якщо Ви все-таки наважилися зібрати свій проєкт pyinstaller у exe пропоную розглянути приклад.
Як приклад будемо використовувати мій шаблон для PyQt6
Шаблон дуже простий - показує просте вікно.
Він має файли які задані відносними шляхами:
1️⃣ Одна з переваг Qt - використання файлів "форм" формату
2️⃣ icon.png це іконка у головному вікні, вона задана main_window.ui через дизайнер "форм" QtDesiginer
Напишемо pyinstaller_build.bat скрипт який буде займатись збіркою у exe
Як бачимо всі файли які використовуються програмою треба додавати опцією
Також сам exe файл може мати іконку для цього має бути використана опція
Опція
Опція
Опція
Але цього недостатньо, щоб наш додаток знаходив файли main_window.ui та icon.png при запуску треба змінювати робочу директорію (це треба робити на самому початку скрипта).
Атрибут _MEIPASS додається динамічно pyinstaller-ом - це тимчасова тека куди розпаковується проєкт
Без цієї вставки коду буде помилка про те, що вказані файли відсутні.
Також я додам скріншот з збіркою без опції
Додаткові файли будуть прикріплені у коментарях.
#PyInstaller #PyQt6
Якщо Ви все-таки наважилися зібрати свій проєкт pyinstaller у exe пропоную розглянути приклад.
Як приклад будемо використовувати мій шаблон для PyQt6
Шаблон дуже простий - показує просте вікно.
Він має файли які задані відносними шляхами:
1️⃣ Одна з переваг Qt - використання файлів "форм" формату
*.ui в даному випадку це - main_window.ui2️⃣ icon.png це іконка у головному вікні, вона задана main_window.ui через дизайнер "форм" QtDesiginer
Напишемо pyinstaller_build.bat скрипт який буде займатись збіркою у exe
SET SCRIPT_NAME=main.py
SET EXE_NAME=prog
.venv\Scripts\pyinstaller.exe ^
--add-data "main_window.ui;." ^
--add-data "icon.png;." ^
--icon "icon.ico" ^
--windowed ^
--onefile ^
--noupx ^
--name %EXE_NAME% ^
%SCRIPT_NAME%
pause
Як бачимо всі файли які використовуються програмою треба додавати опцією
--add-dataТакож сам exe файл може мати іконку для цього має бути використана опція
--icon але треба зауважити що формат іконки має бути саме .ico (png не підходить).Опція
--windowed саме для GUI застосунків щоб сховати вікно консолі. Опція
--onefile саме збірка у exeОпція
--noupx збирати без upx стиснення.Але цього недостатньо, щоб наш додаток знаходив файли main_window.ui та icon.png при запуску треба змінювати робочу директорію (це треба робити на самому початку скрипта).
try:
import os, sys
os.chdir(sys._MEIPASS)
print(f"{sys._MEIPASS=}")
except AttributeError:
pass
Атрибут _MEIPASS додається динамічно pyinstaller-ом - це тимчасова тека куди розпаковується проєкт
Без цієї вставки коду буде помилка про те, що вказані файли відсутні.
Також я додам скріншот з збіркою без опції
--windowed щоб можна було побачити як виглядає sys._MEIPASSДодаткові файли будуть прикріплені у коментарях.
#PyInstaller #PyQt6
👍4❤3
Схемка по основам git
яка дає уявлення які можуть бути стани репозиторію і які команди відповідають переходам між ними.
https://www.youtube.com/watch?v=G5nhfQ_lfNg
яка дає уявлення які можуть бути стани репозиторію і які команди відповідають переходам між ними.
https://www.youtube.com/watch?v=G5nhfQ_lfNg
👍2
Forwarded from PythonFromYouTube
Python Decoded Процеси, Потоки, GIL та Asyncio - Введення у Асинхронне Програмування (10-10 26.08.25)
YouTube
Введення у Асинхронне Програмування - Процеси, Потоки, GIL та Asyncio
В цьому відео ми будемо говорити про Асинхронне програмування. Дізнаємося різницю між процесами та потоками їх сильні та слабкі сторони. Також спробуємо зрозуміти що таке GIL, як від нього намагаються позбутись, і навіщо був створений Asyncio.
Підтримати…
Підтримати…
👍1
Теорія сесіям і JWT токенам:
https://www.youtube.com/watch?v=Zk9drnLo590
- частина 1. Що обрати?
https://www.youtube.com/watch?v=750hPr9ZDFM
- частина 2. Безпека
https://www.youtube.com/watch?v=Zk9drnLo590
- частина 1. Що обрати?
https://www.youtube.com/watch?v=750hPr9ZDFM
- частина 2. Безпека
YouTube
Сесії проти JWT #1: Що обрати?
Чим сесії краще за JWT? А де без JWT ніяк? На цих питання зрізаються іноді навіть люди, що претендують на Senior-позиції! Давайте разом розбиратися
---
Навалити базу та підтримати проєкт ви можете за посиланням https://base.monobank.ua/39Tq2sVxaxau6d
Долучайтеся…
---
Навалити базу та підтримати проєкт ви можете за посиланням https://base.monobank.ua/39Tq2sVxaxau6d
Долучайтеся…
🔷 Використання SQLite разом з SqlAlchemy
⚠️ Цікавий нюанс: SQLite за замовчуванням не перевіряє зовнішні ключі.
У багатьох СУБД (PostgreSQL, MySQL) зовнішні ключі завжди перевіряються.
🔧 У SQLite за це відповідає прапорець
За замовчуванням він
👉 Виставити цей прапорець можна таким чином:
Або одразу оголосити обробник події:
✅ Так Ви уникнете "тихих" проблем з цілісністю даних.
#sqlite #sqlalchemy
⚠️ Цікавий нюанс: SQLite за замовчуванням не перевіряє зовнішні ключі.
У багатьох СУБД (PostgreSQL, MySQL) зовнішні ключі завжди перевіряються.
🔧 У SQLite за це відповідає прапорець
foreign_keys. За замовчуванням він
OFF, і якщо його не виставити в ON, можна отримати неузгоджені дані у зв’язаних таблицях, і довго дивуватись чому так.👉 Виставити цей прапорець можна таким чином:
async with engine.begin() as connection:
await connection.execute("PRAGMA foreign_keys=ON")
Або одразу оголосити обробник події:
from sqlalchemy import event
from sqlalchemy.engine import Engine
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, _):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
✅ Так Ви уникнете "тихих" проблем з цілісністю даних.
#sqlite #sqlalchemy
👍2
🔶 Requests. Простий GET-запит.
У Python HTTP-запити можна робити вбудованою бібліотекою urllib.
Але значно зручніше використовувати сторонню бібліотеку requests. Варто також згадати інші бібліотеки зі схожим інтерфейсом — наприклад, httpx та curl_cffi. Вони можуть працювати асинхронно та мають більш наближені до браузерних TLS-відбитки, що зменшує ймовірність бану при скрапінгу.
Це простий приклад GET-запиту для отримання HTML-сторінки.
HTML-код виводиться в консоль як рядок і зберігається у файл у байтовому вигляді.
Для різних HTTP-методів є відповідні методи в requests. Додаткові дані можна передавати через аргументи методів (заголовки, параметри запиту, тіло, проксі тощо).
⚠️ Поширена помилка початківців — забути перевірити код відповіді сервера. Найпростіше це зробити викликом raise_for_status(), який підніме виняток, якщо код відповіді не в межах 200–399.
Але також можна перевіряти атрибут status_code.
#http #requests #GET
У Python HTTP-запити можна робити вбудованою бібліотекою urllib.
Але значно зручніше використовувати сторонню бібліотеку requests. Варто також згадати інші бібліотеки зі схожим інтерфейсом — наприклад, httpx та curl_cffi. Вони можуть працювати асинхронно та мають більш наближені до браузерних TLS-відбитки, що зменшує ймовірність бану при скрапінгу.
import requests
response = requests.get("https://example.com/")
response.raise_for_status()
print(response.text)
with open("content.html", "wb") as file:
file.write(response.content)
Це простий приклад GET-запиту для отримання HTML-сторінки.
HTML-код виводиться в консоль як рядок і зберігається у файл у байтовому вигляді.
Для різних HTTP-методів є відповідні методи в requests. Додаткові дані можна передавати через аргументи методів (заголовки, параметри запиту, тіло, проксі тощо).
⚠️ Поширена помилка початківців — забути перевірити код відповіді сервера. Найпростіше це зробити викликом raise_for_status(), який підніме виняток, якщо код відповіді не в межах 200–399.
Але також можна перевіряти атрибут status_code.
#http #requests #GET
👍4
🔷 Requests. GET з параметрами та заголовками.
Для прикладу виконаємо запит до погодного API
https://api.open-meteo.com/v1/forecast?latitude=50.4501&longitude=30.5234¤t_weather=True&timezone=Europe/Kyiv
Основні моменти:
1️⃣ Параметри запиту передаються у вигляді словника у метод, бібліотека кодує їх
2️⃣ Суто для демонстрації змінюємо заголовки запиту (User-Agent)
3️⃣ Об'єкт response має метод json який перетворює json-відповідь у python об'єкт (зазвичай словник)
#http #requests #GET
Для прикладу виконаємо запит до погодного API
https://api.open-meteo.com/v1/forecast?latitude=50.4501&longitude=30.5234¤t_weather=True&timezone=Europe/Kyiv
import requests
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": 50.4501,
"longitude": 30.5234,
"current_weather": True,
"timezone": "Europe/Kyiv"
}
headers = {
"User-Agent": "my-script/1.0",
}
response = requests.get(url, params=params, headers=headers)
response.raise_for_status()
json_content = response.json()
current_weather = json_content["current_weather"]
print("Температура в Києві:", current_weather["temperature"])
print("Швидкість вітру:", current_weather["windspeed"])
Основні моменти:
1️⃣ Параметри запиту передаються у вигляді словника у метод, бібліотека кодує їх
2️⃣ Суто для демонстрації змінюємо заголовки запиту (User-Agent)
3️⃣ Об'єкт response має метод json який перетворює json-відповідь у python об'єкт (зазвичай словник)
#http #requests #GET
👍3
🔶 Requests. POST form-urlencoded
POST використовується для створення ресурсів або надсилання даних на сервер. Дані передаються у тілі запиту, а не у URL (як при GET).
Є різні типи POST-запитів:
🔺 application/x-www-form-urlencoded – дані форми кодуються у вигляді
🔺 application/json – дані у вигляді json
🔺 multipart/form-data – форми з файлами.
Даний приклад демонструє передачу даних форми (form-urlencoded)
Бібліотека автоматично виставляє заголовок відповідно до типу:
Форми часто використовується для авторизації на сайтах: у даних передаються логін і пароль. Але у даному випадку ми передаємо текст і розмір картинки, а сайт повертає нам QR-код картинку.
#http #requests #POST
POST використовується для створення ресурсів або надсилання даних на сервер. Дані передаються у тілі запиту, а не у URL (як при GET).
Є різні типи POST-запитів:
🔺 application/x-www-form-urlencoded – дані форми кодуються у вигляді
param1=value1¶m2=value2🔺 application/json – дані у вигляді json
🔺 multipart/form-data – форми з файлами.
Даний приклад демонструє передачу даних форми (form-urlencoded)
Бібліотека автоматично виставляє заголовок відповідно до типу:
Content-Type: application/x-www-form-urlencoded Форми часто використовується для авторизації на сайтах: у даних передаються логін і пароль. Але у даному випадку ми передаємо текст і розмір картинки, а сайт повертає нам QR-код картинку.
import requests
url = "https://api.qrserver.com/v1/create-qr-code/"
data = {
"data": "Привіт світ!",
"size": "200x200"
}
response = requests.post(url, data=data)
response.raise_for_status()
with open("qr_code.png", "wb") as file:
file.write(response.content)
#http #requests #POST
👍2
🔷 Requests. POST application/json
POST/application-json використовується для надсилання json даних на сервер (REST API)
Замість параметру data треба використовувати параметр json
У цьому випадку бібліотека requests виставляє заголовок:
Реальне API мені не вдалось знайти тому використаємо для прикладу тестове API:
⚠️ Зверніть увагу що статус кодом який повертається може бути 201, а не 200 що відповідає створенню ресурсу.
Основні статус коди
#http #requests #POST
POST/application-json використовується для надсилання json даних на сервер (REST API)
Замість параметру data треба використовувати параметр json
У цьому випадку бібліотека requests виставляє заголовок:
Content-Type: application/jsonРеальне API мені не вдалось знайти тому використаємо для прикладу тестове API:
import requests
url = "https://jsonplaceholder.typicode.com/posts"
json_payload = {
"title": "foo",
"body": "bar",
"userId": 1
}
response = requests.post(url, json=json_payload)
response.raise_for_status()
print(response.status_code)
print(response.json())
201
{'title': 'foo', 'body': 'bar', 'userId': 1, 'id': 101}
⚠️ Зверніть увагу що статус кодом який повертається може бути 201, а не 200 що відповідає створенню ресурсу.
Основні статус коди
#http #requests #POST
👍1
🔶 Requests. POST multipart/form-data
multipart/form-data використовується у формах з надсилання файлів на сервер.
У цьому випадку бібліотека requests виставляє заголовок:
Для прикладу завантажимо наш qrcode з попереднього прикладу на файлообмінник.
Також будемо вдавати браузер Mozilla.
Для відправки файлів використовується словник files з вказанням:
1️⃣ назви файлу
2️⃣ самого файлу
3️⃣ типу файлу
#http #requests #POST
multipart/form-data використовується у формах з надсилання файлів на сервер.
У цьому випадку бібліотека requests виставляє заголовок:
Content-Type: multipart/form-data; boundary=...Для прикладу завантажимо наш qrcode з попереднього прикладу на файлообмінник.
Також будемо вдавати браузер Mozilla.
Для відправки файлів використовується словник files з вказанням:
1️⃣ назви файлу
2️⃣ самого файлу
3️⃣ типу файлу
import requests
with open("qr_code.png", "rb") as file:
url = "https://catbox.moe/user/api.php"
files = {
"fileToUpload": ("qr_code.png", file, "image/png"),
}
data = {
"reqtype": "fileupload",
"userhash": "",
}
headers = {
"User-Agent" : "Mozilla/5.0 "
"(Windows NT 10.0; Win64; x64; rv:142.0)"
"Gecko/20100101 Firefox/142.0"
}
r = requests.post(url, files=files, data=data, headers=headers)
r.raise_for_status()
print(r.text.strip()) # вивод url
https://files.catbox.moe/lmcc82.png
#http #requests #POST
👎1
🔷 Requests. Використання сесій.
У Python бібліотека requests дозволяє зручно працювати з HTTP-запитами. Якщо потрібно виконати кілька запитів до одного сайту — варто використовувати сесію.
Що дає використання сесії:
1️⃣ Автоматично підтримувати cookies між запитами.
2️⃣ Дозволяють повторно використовувати одні ті самі заголовки.
3️⃣ Використовують одне TCP-з’єднання для кількох запитів → запити виконуються швидше.
Приклад коду з використанням сесій:
#http #requests #session
У Python бібліотека requests дозволяє зручно працювати з HTTP-запитами. Якщо потрібно виконати кілька запитів до одного сайту — варто використовувати сесію.
Що дає використання сесії:
1️⃣ Автоматично підтримувати cookies між запитами.
2️⃣ Дозволяють повторно використовувати одні ті самі заголовки.
3️⃣ Використовують одне TCP-з’єднання для кількох запитів → запити виконуються швидше.
Приклад коду з використанням сесій:
import requests
url = "https://httpbin.org/headers"
with requests.Session() as session:
# Виставляємо заголовоки для всіх запитів у сесії
headers = {
"User-Agent" : "Mozilla/5.0 "
"(Windows NT 10.0; Win64; x64; rv:142.0)"
"Gecko/20100101 Firefox/142.0"
}
session.headers.update(headers)
r1 = session.get(url)
r1.raise_for_status()
print(r1.json())
r2 = session.get(url)
r2.raise_for_status()
print(r2.json())
#http #requests #session
👍1
🟣 Selectolax. Парсинг HTML
selectolax одна з найшвидших бібліотек для парсингу html. Для пошуку тегів використовується css selectors.
Вона швидша за BeautifulSoup4 і немає проблем з анотаціями типів.
Давайте розглянемо задачу коли треба з html спарсити всі фрукти з такої html сторінки
Для початку створимо об'єкт парсеру:
Шукаєм один тег по id
⚠️ Якщо тег не знайдено метод парсеру вертає None тому завжди варто перевіряти цей момент щоб отримати помилку зі зрозумілим описом. Для цього можна використовувати assert або використати if і кидати Exception.
В середині знайденого тегу шукаємо список по імені тегу:
Використовуємо пошук по імені класу тега щоб знайти всі елементи списку
🔺 strip=True - видаляє зайві пробіли всередині тексту дочірніх тегів
🔺 separator - задає розділювач між текстами з різних дочірніх тегів
🔺 .strip() - обрізає пробіли (та переводи рядків) з початку і кінця рядка
Вивід коду:
#selectolax #parsing #scraping
selectolax одна з найшвидших бібліотек для парсингу html. Для пошуку тегів використовується css selectors.
Вона швидша за BeautifulSoup4 і немає проблем з анотаціями типів.
Давайте розглянемо задачу коли треба з html спарсити всі фрукти з такої html сторінки
html_content = """
<html>
<body>
<section id="fruits">
<h2>Fruits</h2>
<ul>
<li class="item red-item">🍎 Apple</li>
<li class="item">🍌 Banana</li>
<li class="item"> 🍊 <span style="color: orange;">Orange</span> </li>
</ul>
</section>
<section id="vegetables">
<h2>Vegetables</h2>
<ul>
<li class="item">🥕 Carrot</li>
<li class="item" data-id="42">🥔 Potato</li>
<li class="item" data-id="69">🍆 Eggplant</li>
</ul>
</section>
<a href="https://t.me/Python_Materials_For_Beginners/170">Parsing</a>
</body>
</html>
"""
Для початку створимо об'єкт парсеру:
from selectolax.lexbor import LexborHTMLParser, LexborNode
parser = LexborHTMLParser(html_content)
Шукаєм один тег по id
container_el: LexborNode | None = parser.css_first("section#fruits")
assert container_el, "Fruits container not found!"⚠️ Якщо тег не знайдено метод парсеру вертає None тому завжди варто перевіряти цей момент щоб отримати помилку зі зрозумілим описом. Для цього можна використовувати assert або використати if і кидати Exception.
В середині знайденого тегу шукаємо список по імені тегу:
list_el = container_el.css_first("ul")
assert list_el, "List of fruits not found!"Використовуємо пошук по імені класу тега щоб знайти всі елементи списку
item_els: list[LexborNode] = list_el.css("li.item")
for item_el in item_els:
text = item_el.text(strip=True, separator="-").strip()
print(text)🔺 strip=True - видаляє зайві пробіли всередині тексту дочірніх тегів
🔺 separator - задає розділювач між текстами з різних дочірніх тегів
🔺 .strip() - обрізає пробіли (та переводи рядків) з початку і кінця рядка
Вивід коду:
🍎 Apple
🍌 Banana
🍊-Orange-
#selectolax #parsing #scraping
🟠 Selectolax. Парсинг HTML. Частина 2.
🔺 Поєднанний пошук.
Пошук по CSS-селекторах дозволяє одразу поєднувати все в одному рядку запиту:
❗️ Але я наполегливо не рекомендував би цим зловживати. Короткий запис — це добре, але у випадку помилки буде важко зрозуміти, з яким саме тегом проблема.
🔺 Пошук тега який має декілька класів
🔺 Атрибути тегу
Для отримання атрибуту тегу :
▪️attributes – це read-only словник. Ти можеш з нього читати, але не змінювати напряму.
▪️attrs – це mutable dict-like (звичайний словник), який можна змінювати.
🔺 Пошук по атрибуту:
#selectolax #parsing #scraping
🔺 Поєднанний пошук.
Пошук по CSS-селекторах дозволяє одразу поєднувати все в одному рядку запиту:
item_els = parser.css("section#fruits ul li.item")
for item_el in item_els:
text = item_el.text(strip=True, separator=" ").strip()
print(text)❗️ Але я наполегливо не рекомендував би цим зловживати. Короткий запис — це добре, але у випадку помилки буде важко зрозуміти, з яким саме тегом проблема.
🔺 Пошук тега який має декілька класів
# <li class="item red-item"> ... </li>
red_item_el = parser.css_first("li.item.red-item")
assert red_item_el
print(red_item_el.text()) # 🍎 Apple
🔺 Атрибути тегу
# <a href=" ... ">Parsing</a>
link_el = parser.css_first("a")
assert link_el
url = link_el.attributes["href"]
print(url) # https://t.me/Python_Materials_For_Beginners/170
Для отримання атрибуту тегу :
▪️attributes – це read-only словник. Ти можеш з нього читати, але не змінювати напряму.
▪️attrs – це mutable dict-like (звичайний словник), який можна змінювати.
🔺 Пошук по атрибуту:
data_els = parser.css("li.item[data-id]")
for data_el in data_els:
data_id = data_el.attributes["data-id"]
print(data_id) # 42 69data_el = parser.css_first("li.item[data-id='42']")
assert data_el
print(data_el.html) # <li class="item" data-id="42"> ... Potato</li>#selectolax #parsing #scraping
👍1
🟢 Selectolax. Парсинг HTML. Підсумки та рекомендації.
Для пошуку тегів ми можемо використовувати:
▪️ id тега
▪️ назву тега
▪️ клас тега
▪️ атрибути тега
❗️ У коректному HTML id завжди повинен бути унікальним, тому пошук по ньому — найнадійніший.
Якщо ж шукати по назві/класу/атрибутам, результатів може бути кілька, і серед них можуть траплятися елементи, які ви не очікували знайти.
У нашому прикладі, якщо ми хочемо тільки фрукти й напишемо:
То отримаємо не лише фрукти, а й овочі — це видно одразу у нашому простому HTML-коду. Реальні html-сторінки по розміру значно більші і можна не помітити десь ще на сторінці використовуються схожі теги але у зовсім іншому контексті, як наслідок — незрозумілі помилки у коді.
👉 Тому рекомендую завжди звужувати пошук: спершу знайдіть найближчий батьківський елемент із логічним id, класом чи атрибутом, а вже потім отримуйте потрібні дочірні теги.
👉 Важливо, щоб назви класів, id чи атрибутів, до яких ви прив’язуєтеся, були логічними та «говорили самі за себе». Так менша ймовірність отримати помилкові результати, а код буде легше читати й підтримувати.
👉 Є певна термінологія в HTML: тег зазвичай називають елементом (DOM element) або нодою (Node). Я відповідно додаю суфікс
#selectolax #parsing #scraping
Для пошуку тегів ми можемо використовувати:
▪️ id тега
▪️ назву тега
▪️ клас тега
▪️ атрибути тега
❗️ У коректному HTML id завжди повинен бути унікальним, тому пошук по ньому — найнадійніший.
Якщо ж шукати по назві/класу/атрибутам, результатів може бути кілька, і серед них можуть траплятися елементи, які ви не очікували знайти.
У нашому прикладі, якщо ми хочемо тільки фрукти й напишемо:
item_els = parser.css("li.item") То отримаємо не лише фрукти, а й овочі — це видно одразу у нашому простому HTML-коду. Реальні html-сторінки по розміру значно більші і можна не помітити десь ще на сторінці використовуються схожі теги але у зовсім іншому контексті, як наслідок — незрозумілі помилки у коді.
👉 Тому рекомендую завжди звужувати пошук: спершу знайдіть найближчий батьківський елемент із логічним id, класом чи атрибутом, а вже потім отримуйте потрібні дочірні теги.
👉 Важливо, щоб назви класів, id чи атрибутів, до яких ви прив’язуєтеся, були логічними та «говорили самі за себе». Так менша ймовірність отримати помилкові результати, а код буде легше читати й підтримувати.
👉 Є певна термінологія в HTML: тег зазвичай називають елементом (DOM element) або нодою (Node). Я відповідно додаю суфікс
_el або _els до змінних, які містять об’єкти тегів. Це не принципово, але, на мою думку, так код читається краще й спрощується іменування змінних.#selectolax #parsing #scraping
👍1
💎 httpx+selectolax. Data scraping.
Розглянимо приклад коду який наводив у чаті . Код достатньо довгий тому Git-Gist
1️⃣ Часті запити на сайт можуть призвести до:
▪️ відповіді HTTP 429 Too Many Requests
▪️ обриву з'єднання сервером
▪️ появу капчі
▪️ блокуванню по IP
Тому варто обмежувати кількість запитів у секунду. Для цього існує бібліотека asynciolimiter яка дає можливість це зробити за допомогою Limiter: перед кожним запитом варто викликати його метод limiter.wait()
2️⃣ При скрапінгу даних використовуємо сесії. Це пришвидшує виконання запитів і дає підтримку cookie.
3️⃣ Щоб згрупувати дані разом варто використовувати класи, dataclasses, NamedTuple або як я моделі pydantic
4️⃣ Код варто розбивати на функції, класи, модулі і пакети уникаючи награмодження коду. В даному прикладі я показую розбиття на ф-ції але можна було всю роботу з сайтом винести у модуль або пакет. Також можна було зробити клас QuoteScraper з відповідними методами (це дозволило б не передавати постійно session та limiter у параметрах).
📦
┣━━ 📜
┣━━ ⚙️
┣━━ 🧾
┣━━ 🔎
┗━━ 🕷
📜
Структура має бути не обов'язково така сама, але вона має
бути. Коли весь проєкт у одному файлі — це не норм.
5️⃣ Особисто я використовую такий неймінг:
5.1. Функції які займаютья парсингом HTML назвиваю як
parse_ *
5.2. Функціїї які роблять запити: scrape_*
також можна назвивати get_* або fetch_*
6️⃣ Для перевірки наявності потрібних використовую assert але можна також кидати Exception/RuntimeError
7️⃣ Використання logging дає змогу налаштовувати кількість/рівень повідомлень у консоль як власного коду так і коду використаних бібліотек.
8️⃣ Використання генераторів та ітераторів дає можливість більш гнучко використовувати написаний код. (наприклад зупинити ітерацію по сторінкам коли знайдена потрібна цитата)
#httpx #selectolax #parsing #scraping
Розглянимо приклад коду який наводив у чаті . Код достатньо довгий тому Git-Gist
1️⃣ Часті запити на сайт можуть призвести до:
▪️ відповіді HTTP 429 Too Many Requests
▪️ обриву з'єднання сервером
▪️ появу капчі
▪️ блокуванню по IP
Тому варто обмежувати кількість запитів у секунду. Для цього існує бібліотека asynciolimiter яка дає можливість це зробити за допомогою Limiter: перед кожним запитом варто викликати його метод limiter.wait()
2️⃣ При скрапінгу даних використовуємо сесії. Це пришвидшує виконання запитів і дає підтримку cookie.
3️⃣ Щоб згрупувати дані разом варто використовувати класи, dataclasses, NamedTuple або як я моделі pydantic
4️⃣ Код варто розбивати на функції, класи, модулі і пакети уникаючи награмодження коду. В даному прикладі я показую розбиття на ф-ції але можна було всю роботу з сайтом винести у модуль або пакет. Також можна було зробити клас QuoteScraper з відповідними методами (це дозволило б не передавати постійно session та limiter у параметрах).
📦
quote_scraper┣━━ 📜
__init__.py ┣━━ ⚙️
config.py - константи, наприклад BASE_URL ┣━━ 🧾
schemas.py - моделі даних┣━━ 🔎
parsers.py - функції для парсингу html┗━━ 🕷
scrapers.py - функції для запит+парсинг 📜
main.pyСтруктура має бути не обов'язково така сама, але вона має
бути. Коли весь проєкт у одному файлі — це не норм.
5️⃣ Особисто я використовую такий неймінг:
5.1. Функції які займаютья парсингом HTML назвиваю як
parse_ *
5.2. Функціїї які роблять запити: scrape_*
також можна назвивати get_* або fetch_*
6️⃣ Для перевірки наявності потрібних використовую assert але можна також кидати Exception/RuntimeError
7️⃣ Використання logging дає змогу налаштовувати кількість/рівень повідомлень у консоль як власного коду так і коду використаних бібліотек.
8️⃣ Використання генераторів та ітераторів дає можливість більш гнучко використовувати написаний код. (наприклад зупинити ітерацію по сторінкам коли знайдена потрібна цитата)
#httpx #selectolax #parsing #scraping
👍1
🤖 Про телеграм боти.
Телеграм бот це програма яка отримує події/оновлення (Updates) від телеграм сервера і реагує на них, або ігнорує.
Боти можна розділяти по способу отримання оновлень (Update):
1️⃣ Long Polling
2️⃣ Webhook
Long Polling — бот періодично запитує сервер Телеграм, чи є нові оновлення. Цей варіант підходить для більшості ботів.
Webhook — бот отримує оновлення відразу, як тільки вони надходять, бо Телеграм відправляє їх на заданий Вами URL. Цей варіант для високонавантажених ботів.
На відміну від Long polling, для Webhook потрібен публічний IP або домен з SSL, щоб Телеграм міг надсилати запити безпосередньо на твій сервер.
#tg_bots
Телеграм бот це програма яка отримує події/оновлення (Updates) від телеграм сервера і реагує на них, або ігнорує.
Боти можна розділяти по способу отримання оновлень (Update):
1️⃣ Long Polling
2️⃣ Webhook
Long Polling — бот періодично запитує сервер Телеграм, чи є нові оновлення. Цей варіант підходить для більшості ботів.
Webhook — бот отримує оновлення відразу, як тільки вони надходять, бо Телеграм відправляє їх на заданий Вами URL. Цей варіант для високонавантажених ботів.
На відміну від Long polling, для Webhook потрібен публічний IP або домен з SSL, щоб Телеграм міг надсилати запити безпосередньо на твій сервер.
#tg_bots
👍3
Forwarded from PythonFromYouTube
ByteByteGo
Top 3 Things You Should Know About Webhooks!
1 hour ago
https://www.youtube.com/watch?v=x_jjhcDrISk
Top 3 Things You Should Know About Webhooks!
1 hour ago
https://www.youtube.com/watch?v=x_jjhcDrISk
YouTube
Top 3 Things You Should Know About Webhooks!
Get a Free System Design PDF with 158 pages by subscribing to our weekly newsletter: https://bit.ly/bytebytegoytTopic
Animation tools: Adobe Illustrator and After Effects.
Checkout our bestselling System Design Interview books:
Volume 1: https://amzn.to/3Ou7gkd…
Animation tools: Adobe Illustrator and After Effects.
Checkout our bestselling System Design Interview books:
Volume 1: https://amzn.to/3Ou7gkd…