Beautiful Soup — это популярная библиотека Python для парсинга HTML и XML документов. Она позволяет легко извлекать данные из веб-страниц, работая поверх библиотек для получения страниц, таких как
Ниже приведен пример кода, который извлекает заголовки статей и ссылки с главной страницы блога:
Особенности данного примера:
1. Получение страницы: Используем библиотеку
2. Парсинг HTML: Создаем объект
3. Поиск элементов: Используем метод
4. Извлечение данных: В цикле проходим по каждому элементу
5. Вывод результатов: Печатаем заголовки и ссылки в удобочитаемом формате.
Особенности Beautiful Soup:
- Простота использования: Интуитивно понятный синтаксис для навигации и поиска элементов в дереве HTML.
- Поддержка разных парсеров: Можно использовать разные парсеры, такие как
- Обработка невалидного HTML: Beautiful Soup хорошо справляется с разбором некорректно сформированного HTML, что часто встречается на реальных веб-сайтах.
- Мощные инструменты поиска: Методы
- Извлечение текста и атрибутов: Легко получать текст внутри элементов с помощью
Важно учитывать:
- Уважение к правилам сайта: Перед парсингом убедитесь, что вы имеете право собирать данные с сайта. Проверьте файл
- Эффективность: Для небольших проектов или единоразового сбора данных Beautiful Soup подходит идеально. Однако для больших объемов данных или сложных сайтов стоит рассмотреть использование Scrapy.
- Обработка динамического контента: Beautiful Soup не выполняет JavaScript. Для сайтов с динамическим контентом потребуется использовать Selenium или запросы к API.
Заключение
Beautiful Soup — отличный инструмент для быстрого и простого веб-скрейпинга. Он особенно полезен, когда нужно извлечь данные из статических веб-страниц с минимальными усилиями.
Подпишись 👉🏻 @KodduuPython 🤖
requests.Ниже приведен пример кода, который извлекает заголовки статей и ссылки с главной страницы блога:
import requests
from bs4 import BeautifulSoup
# URL страницы, которую будем парсить
url = 'https://example-blog-website.com/'
# Отправляем GET-запрос к странице
response = requests.get(url)
# Проверяем статус ответа
if response.status_code == 200:
# Создаем объект BeautifulSoup
soup = BeautifulSoup(response.content, 'html.parser')
# Находим все элементы с классом 'post'
posts = soup.find_all('div', class_='post')
# Извлекаем заголовки и ссылки
for post in posts:
title = post.find('h2').get_text()
link = post.find('a')['href']
print(f'Заголовок: {title}')
print(f'Ссылка: {link}\n')
else:
print('Не удалось получить страницу')
Особенности данного примера:
1. Получение страницы: Используем библиотеку
requests для отправки HTTP-запроса к целевому URL. Проверяем статус ответа, чтобы убедиться в успешном получении страницы.2. Парсинг HTML: Создаем объект
BeautifulSoup, передавая в него содержимое страницы и используемый парсер (`'html.parser'`).3. Поиск элементов: Используем метод
find_all() для поиска всех div с классом 'post'. Это возвращает список элементов, соответствующих заданным критериям.4. Извлечение данных: В цикле проходим по каждому элементу
post, извлекаем заголовок статьи с помощью find('h2').get_text() и ссылку с помощью find('a')['href'].5. Вывод результатов: Печатаем заголовки и ссылки в удобочитаемом формате.
Особенности Beautiful Soup:
- Простота использования: Интуитивно понятный синтаксис для навигации и поиска элементов в дереве HTML.
- Поддержка разных парсеров: Можно использовать разные парсеры, такие как
'html.parser', lxml или html5lib, в зависимости от потребностей и установленных библиотек.- Обработка невалидного HTML: Beautiful Soup хорошо справляется с разбором некорректно сформированного HTML, что часто встречается на реальных веб-сайтах.
- Мощные инструменты поиска: Методы
find(), find_all(), select() позволяют искать элементы по тегам, классам, идентификаторам и CSS-селекторам.- Извлечение текста и атрибутов: Легко получать текст внутри элементов с помощью
.get_text() и значения атрибутов через доступ как к словарю (`element['attribute']`).Важно учитывать:
- Уважение к правилам сайта: Перед парсингом убедитесь, что вы имеете право собирать данные с сайта. Проверьте файл
robots.txt и условия использования ресурса.- Эффективность: Для небольших проектов или единоразового сбора данных Beautiful Soup подходит идеально. Однако для больших объемов данных или сложных сайтов стоит рассмотреть использование Scrapy.
- Обработка динамического контента: Beautiful Soup не выполняет JavaScript. Для сайтов с динамическим контентом потребуется использовать Selenium или запросы к API.
Заключение
Beautiful Soup — отличный инструмент для быстрого и простого веб-скрейпинга. Он особенно полезен, когда нужно извлечь данные из статических веб-страниц с минимальными усилиями.
Подпишись 👉🏻 @KodduuPython 🤖
Octoparse — это мощный инструмент для веб-скрейпинга с графическим интерфейсом, который также предоставляет API для программного управления задачами и получения данных. С помощью Python вы можете взаимодействовать с Octoparse API для запуска задач, проверки их статуса и извлечения результатов.
Ниже приведен пример кода на Python, который запускает задачу в Octoparse и получает результаты:
Особенности данного примера:
1. Аутентификация: Используется
2. Запуск задачи: Функция
3. Проверка статуса задачи: С помощью функции
4. Получение данных: После завершения задачи функция
5. Структура кода: Код разделен на функции для удобства повторного использования и улучшения читаемости.
Особенности использования Octoparse с Python:
- Интеграция с API: Octoparse предоставляет RESTful API, что позволяет легко интегрировать его с Python с помощью HTTP-запросов.
- Обработка больших объемов данных: Octoparse способен обрабатывать большие объемы данных, а с помощью Python вы можете автоматизировать процессы извлечения и обработки этих данных.
- Гибкость: Возможность настраивать задачи в Octoparse и управлять ими программно дает высокую степень гибкости в веб-скрейпинге.
- Асинхронность: Поскольку задачи выполняются на серверах Octoparse, ваш скрипт может запускать задачи и продолжать выполнение без ожидания их завершения.
Ниже приведен пример кода на Python, который запускает задачу в Octoparse и получает результаты:
import requests
import json
import time
# Ваш API-ключ Octoparse
api_key = 'YOUR_API_KEY'
# ID задачи, которую вы хотите запустить
task_id = 'YOUR_TASK_ID'
# Функция для запуска задачи
def run_task(api_key, task_id):
url = 'https://dataapi.octoparse.com/api/task/startTask'
headers = {'Content-Type': 'application/json'}
payload = {
'taskId': task_id,
'apiKey': api_key
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
return response.json()
# Функция для проверки статуса задачи
def check_task_status(api_key, task_id):
url = 'https://dataapi.octoparse.com/api/task/getTaskStatus'
headers = {'Content-Type': 'application/json'}
payload = {
'taskId': task_id,
'apiKey': api_key
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
return response.json()
# Функция для получения данных
def get_data(api_key, task_id):
url = 'https://dataapi.octoparse.com/api/alldata/getData'
headers = {'Content-Type': 'application/json'}
payload = {
'taskId': task_id,
'apiKey': api_key,
'size': 100, # Количество записей для получения
'skip': 0 # Пропустить первые N записей
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
return response.json()
# Запуск задачи
print('Запуск задачи...')
run_response = run_task(api_key, task_id)
if run_response.get('success'):
print('Задача успешно запущена.')
else:
print('Ошибка при запуске задачи:', run_response.get('message'))
exit()
# Проверка статуса задачи
print('Ожидание завершения задачи...')
while True:
status_response = check_task_status(api_key, task_id)
if status_response.get('success'):
status = status_response['data']['status']
print('Текущий статус задачи:', status)
if status == 'Completed':
print('Задача завершена.')
break
else:
print('Ошибка при проверке статуса:', status_response.get('message'))
break
time.sleep(10) # Ждем 10 секунд перед следующей проверкой
# Получение данных
print('Получение данных...')
data_response = get_data(api_key, task_id)
if data_response.get('success'):
data_list = data_response['data']['dataList']
for item in data_list:
print(item)
else:
print('Ошибка при получении данных:', data_response.get('message'))
Особенности данного примера:
1. Аутентификация: Используется
apiKey для авторизации запросов к API Octoparse.2. Запуск задачи: Функция
run_task отправляет запрос на запуск задачи по ее taskId.3. Проверка статуса задачи: С помощью функции
check_task_status происходит периодическая проверка состояния задачи до ее завершения.4. Получение данных: После завершения задачи функция
get_data извлекает данные, собранные задачей.5. Структура кода: Код разделен на функции для удобства повторного использования и улучшения читаемости.
Особенности использования Octoparse с Python:
- Интеграция с API: Octoparse предоставляет RESTful API, что позволяет легко интегрировать его с Python с помощью HTTP-запросов.
- Обработка больших объемов данных: Octoparse способен обрабатывать большие объемы данных, а с помощью Python вы можете автоматизировать процессы извлечения и обработки этих данных.
- Гибкость: Возможность настраивать задачи в Octoparse и управлять ими программно дает высокую степень гибкости в веб-скрейпинге.
- Асинхронность: Поскольку задачи выполняются на серверах Octoparse, ваш скрипт может запускать задачи и продолжать выполнение без ожидания их завершения.
⚡2
Важно учитывать:
- API-ключ: Ваш API-ключ должен быть защищен. Не размещайте его в общедоступных репозиториях и используйте переменные окружения или файлы конфигурации для его хранения.
- Ограничения API: У Octoparse есть ограничения на количество запросов и объема данных, зависящие от вашего тарифного плана.
- Законность: Убедитесь, что вы соблюдаете все правовые нормы и условия использования веб-сайтов, с которых собираете данные.
- Обработка ошибок: В реальном применении добавьте более детальную обработку ошибок и исключений для повышения надежности вашего скрипта.
Заключение
Использование Octoparse вместе с Python позволяет сочетать простоту настройки задач через графический интерфейс с мощью программной автоматизации. Это идеальное решение для сложных проектов по сбору данных, где требуется надежность и масштабируемость.
Подпишись 👉🏻 @KodduuPython 🤖
- API-ключ: Ваш API-ключ должен быть защищен. Не размещайте его в общедоступных репозиториях и используйте переменные окружения или файлы конфигурации для его хранения.
- Ограничения API: У Octoparse есть ограничения на количество запросов и объема данных, зависящие от вашего тарифного плана.
- Законность: Убедитесь, что вы соблюдаете все правовые нормы и условия использования веб-сайтов, с которых собираете данные.
- Обработка ошибок: В реальном применении добавьте более детальную обработку ошибок и исключений для повышения надежности вашего скрипта.
Заключение
Использование Octoparse вместе с Python позволяет сочетать простоту настройки задач через графический интерфейс с мощью программной автоматизации. Это идеальное решение для сложных проектов по сбору данных, где требуется надежность и масштабируемость.
Подпишись 👉🏻 @KodduuPython 🤖
⚡2
Давайте создадим интересную программу на Python, которая рисует фрактальное дерево с помощью модуля
Описание кода:
- Импортируем модуль `turtle`: позволяет создавать графические рисунки.
- Определяем функцию `fractal_tree`: она рисует ветви дерева рекурсивно.
- Если длина ветви больше 5, выполняем следующие действия:
- Движемся вперед на
- Поворачиваем направо на 20 градусов и вызываем функцию снова с уменьшенной длиной ветви.
- Поворачиваем налево на 40 градусов и снова вызываем функцию.
- Поворачиваем направо на 20 градусов, чтобы вернуть исходное направление.
- Движемся назад на
- Настраиваем черепаху `t`:
- Поворачиваем вверх (на 90 градусов).
- Поднимаем перо и отходим назад, чтобы дерево было по центру экрана.
- Опускаем перо и устанавливаем цвет.
- Вызываем функцию `fractal_tree` с начальной длиной ветви 100.
- `turtle.done()`: сохраняет окно открытым после завершения рисования.
Запустив этот код, вы увидите красивое фрактальное дерево, созданное с помощью рекурсии!
Подпишись 👉🏻 @KodduuPython 🤖
turtle.
import turtle
def fractal_tree(branch_len, t):
if branch_len > 5:
t.forward(branch_len)
t.right(20)
fractal_tree(branch_len - 15, t)
t.left(40)
fractal_tree(branch_len - 15, t)
t.right(20)
t.backward(branch_len)
t = turtle.Turtle()
t.left(90)
t.up()
t.backward(100)
t.down()
t.color("green")
fractal_tree(100, t)
turtle.done()
Описание кода:
- Импортируем модуль `turtle`: позволяет создавать графические рисунки.
- Определяем функцию `fractal_tree`: она рисует ветви дерева рекурсивно.
- Если длина ветви больше 5, выполняем следующие действия:
- Движемся вперед на
branch_len.- Поворачиваем направо на 20 градусов и вызываем функцию снова с уменьшенной длиной ветви.
- Поворачиваем налево на 40 градусов и снова вызываем функцию.
- Поворачиваем направо на 20 градусов, чтобы вернуть исходное направление.
- Движемся назад на
branch_len, возвращаясь к исходной точке ветви.- Настраиваем черепаху `t`:
- Поворачиваем вверх (на 90 градусов).
- Поднимаем перо и отходим назад, чтобы дерево было по центру экрана.
- Опускаем перо и устанавливаем цвет.
- Вызываем функцию `fractal_tree` с начальной длиной ветви 100.
- `turtle.done()`: сохраняет окно открытым после завершения рисования.
Запустив этот код, вы увидите красивое фрактальное дерево, созданное с помощью рекурсии!
Подпишись 👉🏻 @KodduuPython 🤖
❤1
Создадим сложную программу на Python с использованием объектно-ориентированного программирования (ООП). Мы реализуем простой трассировщик лучей (ray tracer), который сможет генерировать изображения 3D-сцен с использованием основных принципов ООП: наследования, полиморфизма, инкапсуляции и абстрактных классов.
import numpy as np
from PIL import Image
from abc import ABC, abstractmethod
class Ray:
def __init__(self, origin, direction):
self.origin = origin # Точка начала луча
self.direction = direction / np.linalg.norm(direction) # Нормализованное направление луча
class Material(ABC):
@abstractmethod
def shade(self, hit_point, normal, light_dir):
pass
class LambertianMaterial(Material):
def __init__(self, color):
self.color = color
def shade(self, hit_point, normal, light_dir):
# Диффузное освещение по модели Ламберта
return self.color * max(np.dot(normal, light_dir), 0)
class Sphere:
def __init__(self, center, radius, material):
self.center = center # Центр сферы
self.radius = radius # Радиус сферы
self.material = material # Материал сферы
def intersect(self, ray):
# Решаем квадратное уравнение для пересечения луча со сферой
oc = ray.origin - self.center
a = np.dot(ray.direction, ray.direction)
b = 2.0 * np.dot(oc, ray.direction)
c = np.dot(oc, oc) - self.radius * self.radius
discriminant = b * b - 4 * a * c
if discriminant < 0:
return None # Пересечений нет
else:
sqrt_disc = np.sqrt(discriminant)
t1 = (-b - sqrt_disc) / (2.0 * a)
t2 = (-b + sqrt_disc) / (2.0 * a)
t = min(t1, t2) if t1 > 0 else (t2 if t2 > 0 else None)
if t:
hit_point = ray.origin + t * ray.direction
normal = (hit_point - self.center) / self.radius
return (t, hit_point, normal, self.material)
else:
return None
class Light:
def __init__(self, position, intensity):
self.position = position # Позиция источника света
self.intensity = intensity # Интенсивность света
class Scene:
def __init__(self):
self.objects = [] # Объекты в сцене
self.lights = [] # Источники света в сцене
def add_object(self, obj):
self.objects.append(obj)
def add_light(self, light):
self.lights.append(light)
def render(self, width, height):
aspect_ratio = width / height
camera_origin = np.array([0, 0, 0])
viewport_height = 2.0
viewport_width = aspect_ratio * viewport_height
focal_length = 1.0
# Создаем изображение
image = Image.new("RGB", (width, height))
pixels = image.load()
for j in range(height):
for i in range(width):
u = (i + 0.5) / width
v = (j + 0.5) / height
x = (u - 0.5) * viewport_width
y = (v - 0.5) * viewport_height
direction = np.array([x, -y, -focal_length])
ray = Ray(camera_origin, direction)
color = self.ray_trace(ray)
pixels[i, height - j - 1] = tuple((np.clip(color, 0, 1) * 255).astype(np.uint8))
image.show()
def ray_trace(self, ray):
closest_t = float('inf')
hit_info = None
# Находим ближайший объект пересечения
for obj in self.objects:
result = obj.intersect(ray)
if result and result[0] < closest_t:
closest_t, hit_point, normal, material = result
hit_info = (hit_point, normal, material)
if hit_info:
hit_point, normal, material = hit_info
color = np.zeros(3)
for light in self.lights:
light_dir = light.position - hit_point
light_dir = light_dir / np.linalg.norm(light_dir)
# Проверка на тени
shadow_ray = Ray(hit_point + 1e-5 * normal, light_dir)
in_shadow = False
for obj in self.objects:
shadow_result = obj.intersect(shadow_ray)
if shadow_result and shadow_result[0] > 1e-5:
in_shadow = True
break
if not in_shadow:
color += material.shade(hit_point, normal, light_dir) * light.intensity
return np.clip(color, 0, 1)
else:
return np.array([0.2, 0.7, 1.0]) # Цвет фона
# Создаем сцену
scene = Scene()
# Добавляем объекты
material_red = LambertianMaterial(np.array([1, 0, 0]))
material_green = LambertianMaterial(np.array([0, 1, 0]))
material_blue = LambertianMaterial(np.array([0, 0, 1]))
material_yellow = LambertianMaterial(np.array([1, 1, 0]))
sphere1 = Sphere(np.array([-0.6, 0, -3]), 0.5, material_red)
sphere2 = Sphere(np.array([0.6, 0, -3]), 0.5, material_green)
sphere3 = Sphere(np.array([0, -1000.5, -3]), 1000, material_blue) # Плоскость
sphere4 = Sphere(np.array([0, 0.75, -3]), 0.5, material_yellow)
scene.add_object(sphere1)
scene.add_object(sphere2)
scene.add_object(sphere3)
scene.add_object(sphere4)
# Добавляем источник света
light1 = Light(np.array([5, 5, -5]), 1.2)
light2 = Light(np.array([-5, 5, -5]), 1.0)
scene.add_light(light1)
scene.add_light(light2)
# Рендерим сцену
scene.render(400, 300)
Описание кода:
1. Импортируем необходимые модули:
-
numpy для работы с векторами и матрицами.-
PIL (Python Imaging Library) для создания и отображения изображения.-
abc для создания абстрактных классов.2. Определяем класс `Ray`:
- Представляет луч с
origin (начало) и direction (направление).3. Создаем абстрактный класс `Material`:
- Имеет абстрактный метод
shade, который должен быть реализован в подклассах.4. Класс `LambertianMaterial`:
- Наследует от
Material.- Реализует диффузное освещение по модели Ламберта.
5. Класс `Sphere`:
- Представляет сферу в 3D-пространстве.
- Метод
intersect вычисляет пересечение луча со сферой и возвращает информацию о пересечении.6. Класс `Light`:
- Представляет точечный источник света с позицией и интенсивностью.
7. Класс `Scene`:
- Содержит объекты и источники света.
- Метод
render создает изображение, трассируя лучи из камеры в сцену.- Метод
ray_trace выполняет трассировку луча и вычисляет цвет пикселя.8. Создаем сцену и добавляем объекты:
- Четыре сферы с разными материалами (красный, зеленый, синий, желтый).
- Большая сфера, представляющая плоскость (землю).
9. Добавляем источники света:
- Два точечных источника света для более сложного освещения сцены.
10. Рендерим сцену:
- Вызываем
scene.render с заданными шириной и высотой изображения.Как это работает:
- Трассировка лучей:
- Для каждого пикселя генерируется луч из камеры через плоскость проекции.
- Луч пересекается со всеми объектами сцены, выбирается ближайшее пересечение.
- Если есть пересечение, вычисляется цвет точки с учетом освещения и теней.
- Если пересечений нет, пикселю присваивается цвет фона.
- Освещение и тени:
- Используется модель освещения Ламберта для расчета диффузного освещения.
- Для каждого источника света проверяется, не находится ли точка в тени других объектов.
Основные концепции ООП, используемые в коде:
- Инкапсуляция: Классы
- Наследование:
- Полиморфизм: Метод
- Абстрактные классы и методы: Использование
Как запустить код:
1. Установите необходимые библиотеки:
2. Запустите скрипт.
Что вы увидите:
- Сгенерируется изображение сцены с несколькими разноцветными сферами и плоскостью, освещенными двумя источниками света.
- Сцена будет содержать реалистичные тени и освещение благодаря использованию трассировки лучей.
Дальнейшие улучшения:
- Добавить отражения и преломления для материалов.
- Реализовать дополнительные модели освещения.
- Добавить новые примитивы (плоскости, треугольники).
- Оптимизировать пересечения и добавить ускоряющие структуры данных.
Вывод:
Этот пример демонстрирует, как можно использовать ООП для создания сложных программ, таких как трассировщик лучей. Классы и наследование помогают структурировать код, а полиморфизм позволяет легко расширять функциональность.
Подпишись 👉🏻 @KodduuPython 🤖
Ray, Sphere, Light, Scene и другие скрывают детали реализации и предоставляют интерфейсы для взаимодействия.- Наследование:
LambertianMaterial наследует от абстрактного класса Material.- Полиморфизм: Метод
shade может быть переопределен в разных материалах для создания различных эффектов освещения.- Абстрактные классы и методы: Использование
ABC и abstractmethod для определения интерфейса материалов.Как запустить код:
1. Установите необходимые библиотеки:
pip install numpy pillow
2. Запустите скрипт.
Что вы увидите:
- Сгенерируется изображение сцены с несколькими разноцветными сферами и плоскостью, освещенными двумя источниками света.
- Сцена будет содержать реалистичные тени и освещение благодаря использованию трассировки лучей.
Дальнейшие улучшения:
- Добавить отражения и преломления для материалов.
- Реализовать дополнительные модели освещения.
- Добавить новые примитивы (плоскости, треугольники).
- Оптимизировать пересечения и добавить ускоряющие структуры данных.
Вывод:
Этот пример демонстрирует, как можно использовать ООП для создания сложных программ, таких как трассировщик лучей. Классы и наследование помогают структурировать код, а полиморфизм позволяет легко расширять функциональность.
Подпишись 👉🏻 @KodduuPython 🤖
Давайте разработаем сложную программу на Python с использованием объектно-ориентированного программирования (ООП). Мы создадим простую версию интерпретатора языка программирования, который будет включать парсинг, интерпретацию и выполнение кода на нашем собственном мини-языке.
import re
from abc import ABC, abstractmethod
# Определение абстрактного синтаксического узла
class ASTNode(ABC):
@abstractmethod
def evaluate(self, context):
pass
# Узел для числовых значений
class NumberNode(ASTNode):
def __init__(self, value):
self.value = value
def evaluate(self, context):
return self.value
# Узел для переменных
class VariableNode(ASTNode):
def __init__(self, name):
self.name = name
def evaluate(self, context):
return context.get(self.name, 0)
# Узел для бинарных операций
class BinaryOperationNode(ASTNode):
def __init__(self, left, operator, right):
self.left = left
self.operator = operator
self.right = right
def evaluate(self, context):
left_val = self.left.evaluate(context)
right_val = self.right.evaluate(context)
if self.operator == '+':
return left_val + right_val
elif self.operator == '-':
return left_val - right_val
elif self.operator == '*':
return left_val * right_val
elif self.operator == '/':
return left_val / right_val
# Узел для присваивания
class AssignmentNode(ASTNode):
def __init__(self, variable_name, expression):
self.variable_name = variable_name
self.expression = expression
def evaluate(self, context):
value = self.expression.evaluate(context)
context[self.variable_name] = value
return value
# Узел для вывода на экран
class PrintNode(ASTNode):
def __init__(self, expression):
self.expression = expression
def evaluate(self, context):
value = self.expression.evaluate(context)
print(value)
return value
# Парсер кода
class Parser:
def __init__(self, code):
self.tokens = re.findall(r'\w+|[\+\-\*/=()]', code)
self.position = 0
def parse(self):
nodes = []
while self.position < len(self.tokens):
node = self.parse_statement()
nodes.append(node)
return nodes
def parse_statement(self):
if self.tokens[self.position] == 'print':
self.position += 1
expr = self.parse_expression()
return PrintNode(expr)
else:
return self.parse_assignment()
def parse_assignment(self):
var_name = self.tokens[self.position]
self.position += 1
if self.tokens[self.position] == '=':
self.position += 1
expr = self.parse_expression()
return AssignmentNode(var_name, expr)
else:
raise SyntaxError('Ожидалось "="')
def parse_expression(self):
node = self.parse_term()
while self.position < len(self.tokens) and self.tokens[self.position] in ('+', '-'):
op = self.tokens[self.position]
self.position += 1
right = self.parse_term()
node = BinaryOperationNode(node, op, right)
return node
def parse_term(self):
node = self.parse_factor()
while self.position < len(self.tokens) and self.tokens[self.position] in ('*', '/'):
op = self.tokens[self.position]
self.position += 1
right = self.parse_factor()
node = BinaryOperationNode(node, op, right)
return node
def parse_factor(self):
token = self.tokens[self.position]
if token.isdigit():
self.position += 1
return NumberNode(int(token))
elif token.isalpha():
self.position += 1
return VariableNode(token)
elif token == '(':
self.position += 1
node = self.parse_expression()
if self.tokens[self.position] == ')':
self.position += 1
return node
else:
raise SyntaxError('Ожидалось ")"')
else:
raise SyntaxError(f'Неожиданный токен: {token}')
# Класс интерпретатора
class Interpreter:
def __init__(self):
self.context = {}
def execute(self, nodes):
for node in nodes:
node.evaluate(self.context)
# Пример кода на нашем мини-языке
code = """
x = 10
y = 20
result = x * y + (x - y) / 2
print result
"""
# Парсим и выполняем код
parser = Parser(code)
ast_nodes = parser.parse()
interpreter = Interpreter()
interpreter.execute(ast_nodes)
Описание кода:
1. Импортируем необходимые модули:
-
re для разбивки кода на токены.-
abc для создания абстрактных классов.2. Создаем абстрактный класс `ASTNode`:
- Определяет интерфейс для всех узлов синтаксического дерева.
- Метод
evaluate выполняет узел в заданном контексте переменных.3. Реализуем различные типы узлов:
-
NumberNode для числовых значений.-
VariableNode для переменных.-
BinaryOperationNode для бинарных операций (`+`, -, *, `/`).-
AssignmentNode для операций присваивания.-
PrintNode для вывода значений на экран.4. Создаем класс `Parser`:
- Инициализируется кодом и разбивает его на токены.
- Метод
parse анализирует код и строит список узлов AST.- Методы
parse_statement, parse_assignment, parse_expression, parse_term, parse_factor реализуют разбор различных частей кода.5. Создаем класс `Interpreter`:
- Содержит контекст переменных (`self.context`).
- Метод
execute выполняет список узлов AST.6. Пример кода на нашем мини-языке:
- Присваиваем значения переменным
x и y.- Вычисляем
result с использованием арифметических операций и скобок.- Выводим
result на экран.7. Парсим и выполняем код:
- Создаем экземпляр
Parser и парсим код, получая AST.- Создаем
Interpreter и выполняем AST.Как это работает:
- Парсинг кода:
- Код разбивается на токены (слова, числа, операторы).
- Парсер строит абстрактное синтаксическое дерево (AST), представляющее структуру кода.
- Выполнение кода:
- Интерпретатор проходит по узлам AST и выполняет их.
- Контекст переменных сохраняется в словаре
self.context.- При выполнении арифметических операций вычисляются значения с учетом текущего контекста.
- Пример выполнения:
-
x = 10 — переменной x присваивается значение 10.-
y = 20 — переменной y присваивается значение 20.-
result = x * y + (x - y) / 2 — вычисляется выражение и результат сохраняется в result.-
print result — выводится значение переменной result.Особенности ООП в коде:
- Инкапсуляция:
- Классы узлов AST скрывают детали реализации каждой операции.
- Контекст переменных хранится внутри интерпретатора.
- Наследование и полиморфизм:
- Все узлы AST наследуют от абстрактного класса
ASTNode.- Метод
evaluate переопределяется в каждом узле для специфического поведения.- Абстрактные классы и методы:
- Использование
ABC и @abstractmethod для определения интерфейса узлов.Как запустить код:
1. Убедитесь, что установлен Python 3.x.
2. Сохраните код в файле с расширением `.py`, например, `mini_interpreter.py`.
3. Запустите скрипт:
python mini_interpreter.py
Ожидаемый результат:
- На экране будет выведено число
190, которое является результатом вычисления выражения в переменной result.Возможные улучшения:
- Добавить поддержку дополнительных операторов и функций:
- Операторы сравнения (`==`,
- Логические операторы (`and`,
- Встроенные функции (например,
- Реализовать управление потоком исполнения:
- Условные операторы (`if`, `else`).
- Циклы (`while`, `for`).
- Добавить обработку ошибок и исключений:
- Улучшить сообщения об ошибках синтаксиса и выполнения.
- Оптимизировать парсер:
- Использовать более продвинутые техники парсинга (например, грамматики и генераторы парсеров).
Вывод:
Этот пример демонстрирует, как с помощью ООП можно реализовать интерпретатор простого языка программирования. Такой подход позволяет легко расширять функциональность языка, добавляя новые конструкции и возможности. Это отличное упражнение для понимания принципов парсинга, интерпретации и выполнения кода, а также для практики в использовании ООП в Python.
Подпишись 👉🏻 @KodduuPython 🤖
- Операторы сравнения (`==`,
!=, >, `<`).- Логические операторы (`and`,
or, `not`).- Встроенные функции (например,
sqrt, sin, `cos`).- Реализовать управление потоком исполнения:
- Условные операторы (`if`, `else`).
- Циклы (`while`, `for`).
- Добавить обработку ошибок и исключений:
- Улучшить сообщения об ошибках синтаксиса и выполнения.
- Оптимизировать парсер:
- Использовать более продвинутые техники парсинга (например, грамматики и генераторы парсеров).
Вывод:
Этот пример демонстрирует, как с помощью ООП можно реализовать интерпретатор простого языка программирования. Такой подход позволяет легко расширять функциональность языка, добавляя новые конструкции и возможности. Это отличное упражнение для понимания принципов парсинга, интерпретации и выполнения кода, а также для практики в использовании ООП в Python.
Подпишись 👉🏻 @KodduuPython 🤖
Давайте создадим сложную программу на Python без использования ООП. Мы реализуем алгоритм Быстрого преобразования Фурье (FFT) и применим его для анализа звукового сигнала. Также визуализируем результаты с помощью
Описание кода:
1. Импортируем необходимые модули:
-
-
-
-
2. Функция `read_wave`:
- Читает WAV-файл и возвращает сигнал и частоту дискретизации.
3. Функция `fft`:
- Рекурсивная реализация алгоритма Быстрого преобразования Фурье.
- Разделяет сигнал на четные и нечетные части и рекурсивно вычисляет их преобразования.
- Использует формулу "бабочки" для комбинирования результатов.
4. Основная часть программы:
- Проверяет наличие аргумента командной строки (имя файла).
- Читает звуковой сигнал из файла.
- Обрезает или дополняет сигнал до размера
- Выполняет FFT и получает спектр сигнала.
- Вычисляет частоты, соответствующие каждому значению спектра.
- Визуализирует исходный сигнал и его спектр.
5. Визуализация:
- Первая графика показывает сигнал во временной области.
- Вторая графика показывает амплитудный спектр сигнала в частотной области.
Как использовать:
1. Подготовьте WAV-файл:
- Убедитесь, что у вас есть звуковой файл в формате WAV для анализа.
2. Запустите скрипт:
- В командной строке выполните:
- Замените
3. Просмотрите результаты:
- Появится окно с двумя графиками, отображающими сигнал и его спектр.
Примечания:
- Размер выборки `N`:
- Выбранное значение
- Можно изменить
- Ограничения:
- Данная реализация FFT не оптимизирована и предназначена для образовательных целей.
- Для больших сигналов рекомендуется использовать
Подпишись 👉🏻 @KodduuPython 🤖
matplotlib.
import numpy as np
import matplotlib.pyplot as plt
import wave
import sys
# Чтение звукового файла
def read_wave(filename):
with wave.open(filename, 'r') as wf:
n_frames = wf.getnframes()
frames = wf.readframes(n_frames)
signal = np.frombuffer(frames, dtype=np.int16)
framerate = wf.getframerate()
return signal, framerate
# Реализация алгоритма FFT
def fft(signal):
N = len(signal)
if N <= 1:
return signal
even = fft(signal[::2])
odd = fft(signal[1::2])
T = [np.exp(-2j * np.pi * k / N) * odd[k % (N//2)] for k in range(N//2)]
return [even[k] + T[k] for k in range(N//2)] + \
[even[k] - T[k] for k in range(N//2)]
# Пример использования
if __name__ == "__main__":
# Проверка аргументов командной строки
if len(sys.argv) < 2:
print("Использование: python fft.py <filename.wav>")
sys.exit(1)
filename = sys.argv[1]
signal, framerate = read_wave(filename)
N = 1024 # Размер выборки
# Обрезаем или дополняем сигнал до нужного размера
if len(signal) < N:
signal = np.pad(signal, (0, N - len(signal)), 'constant')
else:
signal = signal[:N]
# Выполняем FFT
spectrum = fft(signal)
# Получаем частоты
freqs = np.fft.fftfreq(N, d=1/framerate)
# Визуализация
plt.figure(figsize=(12, 6))
plt.subplot(121)
plt.plot(np.arange(N), signal)
plt.title('Временная область')
plt.xlabel('Образцы')
plt.ylabel('Амплитуда')
plt.subplot(122)
plt.plot(freqs[:N//2], np.abs(spectrum[:N//2]) * 2 / N)
plt.title('Частотная область')
plt.xlabel('Частота (Гц)')
plt.ylabel('Амплитуда')
plt.tight_layout()
plt.show()
Описание кода:
1. Импортируем необходимые модули:
-
numpy для работы с массивами и математическими операциями.-
matplotlib.pyplot для визуализации.-
wave для работы с WAV-файлами.-
sys для доступа к аргументам командной строки.2. Функция `read_wave`:
- Читает WAV-файл и возвращает сигнал и частоту дискретизации.
3. Функция `fft`:
- Рекурсивная реализация алгоритма Быстрого преобразования Фурье.
- Разделяет сигнал на четные и нечетные части и рекурсивно вычисляет их преобразования.
- Использует формулу "бабочки" для комбинирования результатов.
4. Основная часть программы:
- Проверяет наличие аргумента командной строки (имя файла).
- Читает звуковой сигнал из файла.
- Обрезает или дополняет сигнал до размера
N (1024 образца).- Выполняет FFT и получает спектр сигнала.
- Вычисляет частоты, соответствующие каждому значению спектра.
- Визуализирует исходный сигнал и его спектр.
5. Визуализация:
- Первая графика показывает сигнал во временной области.
- Вторая графика показывает амплитудный спектр сигнала в частотной области.
Как использовать:
1. Подготовьте WAV-файл:
- Убедитесь, что у вас есть звуковой файл в формате WAV для анализа.
2. Запустите скрипт:
- В командной строке выполните:
python fft.py your_audio_file.wav
- Замените
your_audio_file.wav на имя вашего файла.3. Просмотрите результаты:
- Появится окно с двумя графиками, отображающими сигнал и его спектр.
Примечания:
- Размер выборки `N`:
- Выбранное значение
N = 1024 обеспечивает баланс между разрешением по времени и частоте.- Можно изменить
N в коде для анализа большего или меньшего фрагмента сигнала.- Ограничения:
- Данная реализация FFT не оптимизирована и предназначена для образовательных целей.
- Для больших сигналов рекомендуется использовать
numpy.fft.fft для производительности.Подпишись 👉🏻 @KodduuPython 🤖
🎉1
Собрали программу для тех кому некогда, но нужно быстро пройти весь Python + DataScience 👈👈👈
Подпишись 👉🏻 @KodduuPython 🤖
Подпишись 👉🏻 @KodduuPython 🤖
⚡4🔥1