Использование фреймворка Flask для реализации web-приложений

В данной статье я создам свое первое веб-приложения на Flask, а также попрактикуюсь в использовании шаблонов.

Но прежде чем начать, давайте разберемся что такое вообще Flask. Flask– это легкая веб платформа Python, которая предоставляет полезные инструменты и функции для создания веб приложений на языке Python. Это дает разработчикам гибкость и является доступной средой для новых разработчиков, поскольку вы можете быстро создать веб приложение, используя только один файл Python.

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
    return '

Hello, World!

'

В нем мы сначала импортируем объект Flask из пакета flask. Затем используем его для создания экземпляра приложения Flask, присвоив ему имя app. Мы передаем специальную переменную __name__, которая содержит имя текущего модуля Python. Это имя сообщает экземпляру, где он находится; это нужно, потому что Flask устанавливает некоторые пути за кулисами.

Создав экземпляр приложения, мы можем использовать его для обработки входящих веб запросов и отправки ответов пользователю. @app.route — это декоратор, который превращает обычную функцию Python в функцию просмотра Flask, который преобразует возвращаемое значение функции в HTTP-ответ, отображаемый HTTP-клиентом, например, веб браузером. Мы передаем значение ‘/‘ в @app.route (), чтобы указать, что эта функция будет отвечать на веб запросы для URL-адреса /, который является основным URL-адресом.

Функция просмотра hello() возвращает строку в качестве ответа HTTP.

Теперь у нас есть простое приложение Flask в файле Python с именем app1.py.

Далее, необходимо его запустить чтобы увидеть результат функции просмотра hello(), отображаемой в веб браузере. Как это сделать? Во встроенном терминале я прописываю команду set FLASK_APP=app1, благодаря которой я сообщаю Flask, где найти приложение app1. После, прописываю set FLASK_ENV=development, которая говорит о том, что я хочу запустить приложение в режиме разработки (чтобы можно было использовать отладчик для обнаружения ошибок). Наконец, я прописываю flask run. После запуска, вы увидите следующее:

* Serving Flask app 'app1' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 188-110-549
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Эти выходные данные содержат несколько частей информации:
•Название приложения, которое вы запускаете («app1»).
•Среда, в которой выполняется приложение (development).
•Debug mode (Режим отладки): on означает, что отладчик Flask запущен. Это полезно при разработке, поскольку предоставляет подробные сообщения об ошибках, когда что-то идет не так, что упрощает поиск и устранение неисправностей.
•Приложение работает локально по URL-адресу http://127.0.0.1:5000/. 127.0.0.1 — это IP-адрес, который представляет локальный хост вашего компьютера, а: 5000 — это номер порта.
Далее, открываем браузер и введем URL-адрес http://127.0.0.1:5000/. Вы увидите текст “Hello, World!” в качестве ответа. Это подтверждает, что ваше приложение успешно работает.
Кроме этого, можно добавить несколько маршрутов для отображения разных страниц в зависимости от запрошенного URL.

Маршрут — это URL-адрес, который вы можете использовать, чтобы определить, что пользователь получает, когда посещает ваше веб приложение в своем браузере. Например, http://127.0.0.1:5000/ — это основной маршрут, который может использоваться для отображения главной страницы. URL-адрес http://127.0.0.1:5000/about может быть другим маршрутом, используемым для страницы «About», которая дает посетителю некоторую информацию о вашем веб приложении.

Для этого, в app1.py прописываем следующее:

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
    return '

Hello, World!

' @app.route('/about/') def about(): return '

This is a Flask web application.

'

Здесь, мы добавили новую функцию about(). Эта функция украшена декоратором @app.route(), который преобразует ее в функцию представления, которая обрабатывает запросы к конечной точке http://127.0.0.1:5000/about. Для просмотра результата переходим по этому URL-адресу.
Но можно использовать и несколько маршрутов для одной функции просмотра. Для этого, изменяем app1.py следующим образом:

from flask import Flask
app = Flask(__name__)
@app.route('/')
@app.route('/index/')
def hello():
    return '

Hello, World!

' @app.route('/about/') def about(): return '

This is a Flask web application.

'

После добавления этого нового декоратора вы можете получить доступ к странице индекса как по адресу http://127.0.0.1:5000/, так и по адресу http://127.0.0.1:5000/index.

Теперь вы понимаете, что такое маршруты, как использовать их для создания функций просмотра и как добавлять новые маршруты в ваше приложение. Затем вы воспользуетесь динамическими маршрутами, чтобы позволить пользователям управлять ответом приложения.

Кроме этого, хотелось бы разобрать динамические маршруты, то есть мы создадим маршрут, в котором слова, переданные через URL, будут написаны с заглавной буквы, и маршрут, который складывает два числа и отображает результат.

Для этого, открываем наш app1.py и добавляем:

from markupsafe import escape
from flask import Flask
# ...
@app.route('/capitalize//')
def capitalize(word):
    return '

{}

'.format(escape(word.capitalize()))

Этот новый маршрут имеет переменную секцию. Это говорит Flask взять значение из URL-адреса и передать его функции просмотра. Переменная URL передает аргумент ключевого слова функции просмотра capitalize(). Аргумент имеет то же имя, что и переменная URL (в данном случае слово). При этом вы можете получить доступ к слову, переданному через URL-адрес, и ответить его версией с заглавной буквы, используя метод capitalize() в Python.

Мы используем функцию escape (), которую мы импортировали, чтобы отобразить строку слова как текст. Это важно, чтобы избежать атак с использованием межсайтовых сценариев (XSS). Если пользователь отправляет вредоносный код JavaScript вместо слова, escape() отобразит его как текст, а браузер не запустит его, сохраняя безопасность вашего веб приложения.
Чтобы отобразить слово с заглавной буквы внутри заголовка HTML h1, используйте метод Python .format().

Запустив сервер разработки, открыв браузер и передав по следующим URL-адресам. Вы можете заменить выделенные слова любым словом по вашему выбору. Например:

http://127.0.0.1:5000/capitalize/hello
http://127.0.0.1:5000/capitalize/flask
http://127.0.0.1:5000/capitalize/python

Также можно использовать несколько переменных в маршруте. Чтобы продемонстрировать это, необходимо добавить маршрут, который складывает два положительных целых числа и отображает результат.
Откроем файл app1.py для редактирования и добавим в конец файла следующий маршрут:

# ...
@app.route('/add///')
def add(n1, n2):
    return '

{}

'.format(n1 + n2)

В этом маршруте вы используете специальный преобразователь int с переменной URL (/add///), который принимает только положительные целые числа. По умолчанию переменные URL-адреса считаются строками и рассматриваются как таковые.

Запустив сервер разработки, открыв браузер и перейдя по следующему URL-адресу:

http://127.0.0.1:5000/add/5/5/

При разработке веб приложения вы часто будете сталкиваться с ситуациями, когда приложение отображает ошибку вместо ожидаемого поведения. Вы можете неправильно написать переменную или забыть определить или импортировать функцию. Чтобы упростить решение этих проблем, Flask предоставляет отладчик при запуске приложения в режиме разработки. На этом шаге вы узнаете, как исправить ошибки в вашем приложении с помощью отладчика Flask.

Чтобы продемонстрировать, как обрабатывать ошибки, вы создадите маршрут, который приветствует пользователя из списка имен пользователей.
Откроем файл app1.py для редактирования и добавим в конец файла следующий маршрут:

# ...
@app.route('/users//')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    return '

Hi {}

'.format(users[user_id])

В приведенном выше маршруте функция просмотра greet_user() получает аргумент user_id из переменной URL user_id. Мы используем преобразователь int, чтобы принимать положительные целые числа. Внутри функции у нас есть список Python под названием users, который содержит три строки, представляющие имена пользователей. Функция просмотра возвращает строку, которая создается в зависимости от предоставленного user_id. Если user_id равен 0, ответом будет Привет, Боб в теге h2, потому что Боб является первым элементом в списке (значение users[0]).

Запустив сервер разработки, откроем браузер и перейдем по следующим URL-адресам:

http://127.0.0.1:5000/users/0
http://127.0.0.1:5000/users/1
http://127.0.0.1:5000/users/2

Мы получим следующие ответы:

Hi Bob
Hi Jane
Hi Adam

Откроем файл app1.py для редактирования. Чтобы ответить с ошибкой HTTP 404, нам понадобится функция Flask abort(), которую можно использовать для создания ответов об ошибках HTTP. Изменим вторую строку файла, чтобы также импортировать эту функцию:

from markupsafe import escape
from flask import Flask, abort

Затем отредактируем функцию просмотра greet_user(), чтобы она выглядела следующим образом:

# ...
@app.route('/users//')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    try:
        return '

Hi {}

'.format(users[user_id]) except IndexError: abort(404)

Мы использовали попытку выше, чтобы проверить возвращаемое выражение на наличие ошибок. Если ошибки не было, то есть user_id имеет значение, соответствующее индексу в списке пользователей, приложение ответит соответствующим приветствием. Если значение user_id выходит за пределы диапазона списка, возникает исключение IndexError,
и мы используем except, чтобы поймать ошибку и ответить ошибкой HTTP 404 с помощью вспомогательной функции Flask abort().

Теперь, когда сервер разработки запущен, снова посетим тот URL-адрес. На этот раз мы увидим стандартную страницу с ошибкой 404, информирующую пользователя о том, что страница не существует.
Проделав все эти действия, мы имеем общее представление о том, что такое Flask, как его установить и как использовать для написания веб приложения, как запустить сервер разработки и как использовать маршруты и функции просмотра для отображения различных веб страниц, обслуживающих определенные целей. Мы также узнали, как использовать динамические маршруты, чтобы позволить пользователям взаимодействовать с вашим веб приложением через URL-адрес, и как использовать отладчик для устранения ошибок.
Как использовать шаблоны в приложении Flask
1. Визуализация шаблона и использование переменных
Создав просто веб-приложение на Flask, я решил попробовать использование шаблонов. Для этого, я создал файл app2.py.

В него добавляем следующее:

from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello():
    return render_template('index.html')

В этом блоке кода мы импортируем класс Flask и функцию render_template() из пакета flask. Мы используем класс Flask для создания экземпляра приложения Flask с именем app. Затем мы определяем функцию просмотра (которая является функцией Python, которая возвращает ответ HTTP) с именем hello(), используя декоратор app.route(), который преобразует обычную функцию в функцию просмотра. Эта функция представления использует функцию render_template() для визуализации файла шаблона с именем index.html.

Затем нам нужно будет создать файл шаблона index.html в каталоге с именем templates. Flask ищет шаблоны в каталоге templates, который называется шаблонами, поэтому имя важно. Для этого выполним следующую команду, чтобы создать каталог шаблонов:

mkdir templates

Затем откроем файл с именем index.html и добавим следующий HTML код:

FlaskApp
    

Hello World!

Welcome to FlaskApp!

Здесь мы устанавливаем заголовок, добавляем Hello World! сообщение в виде заголовка h1 и создаем сообщение Welcome to FlaskApp! как заголовок h2. Далее запускаем наше приложение. (как это сделать говорилось выше)
Оставим сервер запущенным и откроем файл app2.py для редактирования. Импортируем модуль datetime из стандартной библиотеки Python и отредактируем функцию index(), чтобы файл выглядел следующим образом:

import datetime
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello():
    return render_template('index.html', utc_dt=datetime.datetime.utcnow())

Здесь мы импортировали модуль datetime и передали в шаблон index.html переменную с именем utc_dt со значением datetime.datetime.utcnow(), которое является текущей датой и временем в формате UTC.

Затем, чтобы отобразить значение переменной на странице индекса, откроем файл index.html для редактирования. Отредактируем файл, чтобы он выглядел следующим образом:

 FlaskApp
    

Hello World!

Welcome to FlaskApp!

{{ utc_dt }}

Мы добавили заголовок h2 со специальным разделителем {{...}} для печати значения переменной utc_dt. Откроем браузер и перейдём на главную страницу/
Теперь мы создали страницу индекса с шаблоном HTML в приложении Flask, отрисовали шаблон, передали и отобразили значение переменной. Затем мы избежим повторения кода, используя наследование шаблонов.
2. Использование механизма наследования шаблонов
На этом этапе мы создадим базовый шаблон с содержанием, которым можно будет поделиться с другими шаблонами. Мы отредактируем свой шаблон индекса, чтобы он унаследовал от базового шаблона. Затем мы создадим новую страницу, которая будет служить страницей «О приложении», где пользователи смогут найти дополнительную информацию о вашем приложении.
Для этого, создадим base.html и пропишем следующий код:

 {% block title %} {% endblock %} - FlaskApp
    
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }
    
    
    
{% block content %} {% endblock %}

Большая часть кода в этом файле представляет собой стандартный HTML код, заголовок, некоторые стили для ссылок навигации, панель навигации с двумя ссылками, одна для страницы индекса, другая для еще не созданной страницы «О программе», а также div для содержание страницы. (Ссылки пока не работают; на следующем шаге будет показано, как создавать ссылки между страницами). Однако, следующие выделенные части относятся к шаблонизатору Jinja:

•{% block title %} {% endblock %}: блок, который служит заполнителем для заголовка. Позже вы будете использовать его в других шаблонах, чтобы задать собственный заголовок для каждой страницы в приложении, не переписывая каждый раз весь раздел.
•{% block content %} {% endblock %}: другой блок, который будет заменен содержимым в зависимости от дочернего шаблона (шаблона, наследуемого от base.html), который заменит его.
Теперь, когда у нас есть базовый шаблон, мы можем воспользоваться им, используя наследование. Откроем файл index.html и затем заменим его содержимое следующим:

{% extends 'base.html' %}
{% block content %}
    

{% block title %} Index {% endblock %}

Hello World!

Welcome to FlaskApp!

{{ utc_dt }}

{% endblock %}

Здесь мы используем тег {% extends %} для наследования от шаблона base.html. Затем мы расширяем его, заменяя блок содержимого в базовом шаблоне тем, что находится внутри блока содержимого в предыдущем блоке кода.

Этот блок содержимого содержит тег h1 с текстовым индексом внутри основной надписи, который, в свою очередь, заменяет исходную основную надпись в шаблоне base.html текстовым индексом, так что полный заголовок становится индексом — FlaskApp. Таким образом, мы можем избежать повторения одного и того же текста дважды, поскольку он работает как заголовок страницы, так и заголовок, который появляется под панелью навигации, унаследованной от базового шаблона. Затем у нас есть еще несколько заголовков: один заголовок h1 с текстом Hello World!, заголовок h2 и заголовок h3, содержащий значение переменной utc_dt.

Наследование шаблонов дает нам возможность повторно использовать HTML код, который есть в других шаблонах (в данном случае base.html), без необходимости повторять его каждый раз, когда это необходимо. Сохраним и обновим страницу индекса в браузере. Страница будет выглядеть следующим образом:
Затем мы создаем страницу «About». Открываем файл app2.py, чтобы добавить новый маршрут и добавляем следующее:

# ...
@app.route('/about/')
def about():
return render_template('about.html')

Здесь используется декоратор app.route() для создания функции просмотра с именем about(). В нем мы возвращаем результат вызова функции render_template() с именем файла шаблона about.html в качестве аргумента.

Откроем файл шаблона с именем about.html для редактирования и добавьте следующий код:

{% extends 'base.html' %}
{% block content %}

{% block title %} About {% endblock %}

FlaskApp is a Flask web application written in Python.

{% endblock %}

Здесь мы наследуем базовый шаблон с помощью тега extends, заменяем блок содержимого базового шаблона тегом h1, который также служит заголовком страницы, и добавляем тег h3 с некоторой информацией о приложении.

Когда сервер разработки запущен, перейдем по следующему URL адресу в своем браузере:

http://127.0.0.1:5000/about

3. Связывание страниц
На этом этапе мы свяжем страницы в шаблонах с помощью вспомогательной функции url_for(). Мы добавим две ссылки на панель навигации в свой базовый шаблон, одну для главной страницы и другую для страницы «About».

Сначала откроем базовый шаблон для редактирования и внесите следующие изменения:

{% block title %} {% endblock %} - FlaskApp
nav a {
color: #d64161;
font-size: 3em;
margin-left: 50px;
text-decoration: none;
}


{% block content %} {% endblock %}

Здесь мы используем специальную функцию url_for(), которая возвращает URL адрес функции просмотра, которую мы ему передаем. Первая ссылка ссылается на маршрут функции просмотра hello() (которая является страницей индекса). Вторая ссылка указывает на маршрут функции просмотра about(). Обратите внимание, что мы передаем имя функции просмотра, а не маршрут (/ или /about). Использование функции url_for() для создания URL адресов помогает лучше управлять URL адресами. Если мы жестко запрограммируем URL адреса, наши ссылки сломаются, если мы изменим маршруты. С url_for() мы можем редактировать маршруты и гарантировать, что ссылки будут работать должным образом. Функция url_for() также заботится о других вещах, таких как экранирование специальных символов.

Теперь перейдем на главную страницу и попробуем ссылки на панели навигации. Мы увидим, что они работают.
4. Использование условных выражений и циклов
На этом этапе мы будем использовать операторы if в своих шаблонах, чтобы управлять тем, что отображать в зависимости от определенных условий. Мы также будем использовать циклы for для просмотра списков Python и отображения каждого элемента в списке. Мы добавим новую страницу, на которой будут отображаться комментарии в виде списка. Комментарии с четным порядковым номером будут иметь синий фон, а комментарии с нечетным порядковым номером будут отображаться на сером фоне.

Сначала мы создадим маршрут для страницы комментариев. Откроем файл app2.py для редактирования и добавьте следующий маршрут в конец файла:

# ...
@app.route('/comments/')
def comments():
comments = ['This is the first comment.',
'This is the second comment.',
'This is the third comment.',
'This is the fourth comment.'
]
return render_template('comments.html', comments=comments)

В приведенном выше маршруте у нас есть список Python, называемый комментариями, который содержит четыре элемента. Мы возвращаете файл шаблона с именем comments.html в последней строке, передача переменной с именем comments, содержащей список, в файл шаблона.

Затем создадим и откроем новый файл comments.html в каталоге шаблонов для редактирования и добавим следующий код:

{% extends 'base.html' %}
{% block content %}

{% block title %} Comments {% endblock %}

{% for comment in comments %}

{{ comment }}

{% endfor %}
{% endblock %}

Здесь мы расширяем шаблон base.html и заменяем содержимое блока содержимого. Во-первых, мы используем заголовок h1, который также служит заголовком страницы.
Мы используем цикл Jinja for в строке {% for comment in comments %}, чтобы просмотреть каждый комментарий в списке комментариев (который сохраняется в переменной комментария). Комментарий отображается в теге (p style="font-size: 24px" {{comment}} /p) так же, как мы обычно отображаем переменную в Jinja. Мы сигнализируем о завершении цикла for с помощью ключевого слова {% endfor %}. Это отличается от способа построения циклов for в Python, поскольку в шаблонах Jinja нет специального отступа.

Когда сервер разработки запущен, откроем браузер и перейдем на страницу комментариев:

http://127.0.0.1:5000/comments

5. Использование фильтров
На этом этапе мы узнаем, как использовать фильтры Jinja в своих шаблонах.

Сначала мы преобразуем комментарии на странице комментариев в верхний регистр. Откроем для редактирования шаблон comments.html и отредактируем его, чтобы он выглядел следующим образом:

{% extends 'base.html' %}
{% block content %}

{% block title %} Comments {% endblock %}

{% for comment in comments %} {% if loop.index != 2 %}

#{{ loop.index }}

{{ comment | upper }}

{% endif %} {% endfor %}
{% endblock %}

Здесь мы расширяем шаблон base.html и заменяем содержимое блока содержимого. Во-первых, мы используем заголовок h1, который также служит заголовком страницы.
Мы используем цикл Jinja for в строке {% for comment in comments %}, чтобы просмотреть каждый комментарий в списке комментариев (который сохраняется в переменной комментария). Комментарий отображается в теге ((p style = font-size: 24px {{comment}} /p)) так же, как мы обычно отображаем переменную в Jinja. Мы сигнализируем о завершении цикла for с помощью ключевого слова {% endfor %}. Это отличается от способа построения циклов for в Python, поскольку в шаблонах Jinja нет специального отступа.

Когда сервер разработки запущен, откроем браузер и перейдем на страницу комментариев:

http://127.0.0.1:5000/comments

Фильтры также могут принимать аргументы в круглых скобках. Чтобы продемонстрировать это, воспользуемся фильтром объединения, чтобы объединить все комментарии в списке комментариев.

Откроем шаблон комментариев и отредактируем его, чтобы он выглядел следующим образом:

{% extends 'base.html' %}
{% block content %}

{% block title %} Comments {% endblock %}

{% for comment in comments %} {% if loop.index != 2 %}

#{{ loop.index }}

{{ comment | upper }}

{% endif %} {% endfor %}

{{ comments | join(" | ") }}

{% endblock %}

Другой важный фильтр — это безопасный фильтр, который позволяет отображать доверенный HTML код в браузере. Для его реализации откроем шаблон комментариев и отредактируем его, чтобы он выглядел следующим образом:

{% extends 'base.html' %}
{% block content %}
    

{% block title %} Comments {% endblock %}

{% for comment in comments %} {% if loop.index != 2 %}

#{{ loop.index }}

{{ comment | upper }}

{% endif %} {% endfor %}
{{ "

COMMENTS

" }}

{{ comments | join("


") }}

{% endblock %}

6 — интеграция Bootstrap
Сейчас мы узнаем, как использовать набор инструментов Bootstrap для стилизации нашего приложения. Добавим панель навигации Bootstrap в базовый шаблон, которая будет отображаться на всех страницах, унаследованных от базового шаблона.

Чтобы использовать Bootstrap, нужно добавить его в базовый шаблон, чтобы мы могли использовать его во всех других шаблонах. Откроем свой шаблон base.html для редактирования и запишем:

 
    
    
    
    
    {% block title %} {% endblock %} - FlaskApp
  
  
    
    
{% block content %} {% endblock %}

Большая часть приведенного выше кода — это шаблон Bootstrap, необходимый для его использования. У нас есть несколько метатегов, ссылка на файл CSS Bootstrap в разделе head, а внизу у нас есть ссылка на необязательный JavaScript. Выделенные части кода содержат код Jinja, объясненный в предыдущих шагах.

Обратите внимание, как мы используем определенные теги и классы CSS, чтобы указать Bootstrap, как отображать каждый элемент.

В теге nav выше у нас есть тег a с классом navbar-brand, который определяет ссылку бренда на панели навигации. Внутри тега ul class = ".navbar-nav" у нас есть обычные элементы панели навигации внутри тега a в теге li.

Когда сервер разработки запущен, откроем страницу индекса в своем браузере:

http://127.0.0.1:5000/

Теперь мы знаем, как использовать HTML шаблоны в своем веб-приложении Flask. Мы использовали переменные для передачи данных с сервера в шаблоны, чтобы избежать повторения HTML кода мы использовали наследование шаблонов, встроили такие элементы, как условные выражения if и циклы for, а также ссылки между разными страницами. Мы узнали о фильтрах для изменения текста и отображения надежного HTML, а также интегрировали Bootstrap в свое приложение.

Работа с PDF файлами

Для разбиения отдельного pdf документа на страницы воспользуемся следующей программой

# from PyPDF2 import PdfFileReader, PdfFileWriter
pdf_document = "D:\Надя\Костерин\Поддомены\source\Формула включений и исключений.pdf"
pdf = PdfFileReader(pdf_document)
for page in range(pdf.getNumPages()):
pdf_writer = PdfFileWriter()
current_page = pdf.getPage(page)
pdf_writer.addPage(current_page)
outputFilename = "dist/Форм_вкл_искл-page-{}.pdf".format(page + 1)
with open(outputFilename, "wb") as out:
pdf_writer.write(out)
print("created", outputFilename)

Результат представлен на следующем рисунке

# import fitz
filename = "D:\Надя\Костерин\Поддомены\source\Формула включений и исключений.pdf"
search_term = "множество"
pdf_document = fitz.open(filename)
for current_page in range(len(pdf_document)):
page = pdf_document.loadPage(current_page)
if page.searchFor(search_term):
print("%s найдено на странице %i" % (search_term, current_page+1))

Осуществим поиск в документе Формула включения и исключения.pdf слова «множество».
Результат работы программы представлен ниже.

Добавление водяного знака с помощью PyPDF2
Добавим в pdf файл водяной знак «Черновик». Текст программы


# Добавление водяного знака в одностраничный PDF

import PyPDF2

input_file = "D:\Надя\Костерин\Поддомены\source\Задание 12.3.pdf"
output_file = "dist/Водяной_знак-page-drafted.pdf"
watermark_file = "source/Черновик.pdf"

with open(input_file, "rb") as filehandle_input:
# читать содержимое исходного файла
pdf = PyPDF2.PdfFileReader(filehandle_input)
with open(watermark_file, "rb") as filehandle_watermark:
# читать содержание водяного знака
watermark = PyPDF2.PdfFileReader(filehandle_watermark)
# получить первую страницу оригинального PDF
first_page = pdf.getPage(0)
# получить первую страницу водяного знака PDF
first_page_watermark = watermark.getPage(0)
# объединить две страницы
first_page.mergePage(first_page_watermark)
# создать объект записи PDF для выходного файла
pdf_writer = PyPDF2.PdfFileWriter()
# добавить страницу
pdf_writer.addPage(first_page)
with open(output_file, "wb") as filehandle_output:
# записать файл с водяными знаками в новый файл
pdf_writer.write(filehandle_output)

Результат работы программы

Удаление страниц с помощью pdfrw
Для удаления страниц необходимо установить библиотеку pdfrw. Текст программы приведен ниже.

# Удалите первые две страницы (титульный лист) из PDF

from pdfrw import PdfReader, PdfWriter

input_file = "D:\Надя\Костерин\Поддомены\source\Формула включений и исключений.pdf"
output_file = "dist/Удаление_страниц-page-drafted.pdf"

# Определить объекты чтения и записи
reader_input = PdfReader(input_file)
writer_output = PdfWriter()

# Перейти на страницу один за другим
for current_page in range(len(reader_input.pages)):
if current_page > 1:
writer_output.addpage(reader_input.pages[current_page])
print("adding page %i" % (current_page + 1))

# Записать измененный контент на диск
writer_output.write(output_file)

Результат работы программы – сформирован новый файл, у которого вырезано 2 первые страницы.

Сканер поддоменов на Python

Если необходимо обнаружить поддомены конкретного Web - сайта, то можно воспользоваться следующей программой. Используется метод полного перебора, будут проверяться все общие имена поддоменов этого конкретного домена, если будет получен ответ от сервера, то это означает, что поддомен существует. Был составлен список поддоменов для сканирования и помещен в файл «subdomains.txt».

#import requests
# домен для поиска поддоменов
domain = "susu.ru"
# читать все поддомены
file = open("D:\Надя\Костерин\Поддомены\subdomains.txt")
# прочитать весь контент
content = file.read()
# разделить на новые строки
subdomains = content.splitlines()
# список обнаруженных поддоменов
discovered_subdomains = []
for subdomain in subdomains:
# создать URL
url = f"http://{subdomain}.{domain}"
try:
# если возникает ОШИБКА, значит, субдомен не существует
requests.get(url)
except requests.ConnectionError:
# если поддомена не существует, просто передать, ничего не выводить
pass
else:
print("[+] Обнаружен поддомен:", url)
# добавляем обнаруженный поддомен в наш список
discovered_subdomains.append(url)
# сохраняем обнаруженные поддомены в файл
with open("discovered_subdomains.txt", "w") as f:
for subdomain in discovered_subdomains:
print(subdomain, file=f)

В результате работы программы были получены следующие результаты для домена susu.ru :
"D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\python.exe" D:/Регина/Костерин/Поддомены/Сканерподдоменов.py
[+] Обнаружен поддомен: http://mail.susu.ru
[+] Обнаружен поддомен: http://test.susu.ru
[+] Обнаружен поддомен: http://lists.susu.ru
[+] Обнаружен поддомен: http://support.susu.ru
[+] Обнаружен поддомен: http://wiki.susu.ru
[+] Обнаружен поддомен: http://media.susu.ru
[+] Обнаружен поддомен: http://my.susu.ru
[+] Обнаружен поддомен: http://sites.susu.ru
[+] Обнаружен поддомен: http://info.susu.ru
[+] Обнаружен поддомен: http://office.susu.ru
Process finished with exit code 0

Работа с EMail

Для того чтобы читать электронные письма, можно использовать вот этот код:

import imaplib
import email
from email.header import decode_header
import webbrowser
import os
# учетные данные
username = ""
password = "password"
def clean(text):
# чистый текст для создания папки
return "".join(c if c.isalnum() else "_" for c in text)
# create an IMAP4 class with SSL
imap = imaplib.IMAP4_SSL("imap.gmail.com")
# authenticate
imap.login(username, password)
status, messages = imap.select("INBOX")
# количество популярных писем для получения
N = 1
# общее количество писем
messages = int(messages[0])
for i in range(messages, messages-N, -1):
# fetch the email message by ID
res, msg = imap.fetch(str(i), "(RFC822)")
for response in msg:
if isinstance(response, tuple):
# parse a bytes email into a message object
msg = email.message_from_bytes(response[1])
# decode the email subject
subject, encoding = decode_header(msg["Subject"])[0]
if isinstance(subject, bytes):
# if it's a bytes, decode to str
subject = subject.decode(encoding)
# decode email sender
From, encoding = decode_header(msg.get("From"))[0]
if isinstance(From, bytes):
From = From.decode(encoding)
print("Subject:", subject)
print("From:", From)
# if the email message is multipart
if msg.is_multipart():
# iterate over email parts
for part in msg.walk():
# extract content type of email
content_type = part.get_content_type()
content_disposition = str(part.get("Content-Disposition"))
try:
# get the email body
body = part.get_payload(decode=True).decode()
except:
pass
if content_type == "text/plain" and "attachment" not in content_disposition:
# print text/plain emails and skip attachments
print(body)
elif "attachment" in content_disposition:
# download attachment
filename = part.get_filename()
if filename:
folder_name = clean(subject)
if not os.path.isdir(folder_name):
# make a folder for this email (named after the subject)
os.mkdir(folder_name)
filepath = os.path.join(folder_name, filename)
# download attachment and save it
open(filepath, "wb").write(part.get_payload(decode=True))
else:
# extract content type of email
content_type = msg.get_content_type()
# get the email body
body = msg.get_payload(decode=True).decode()
if content_type == "text/plain":
# print only text email parts
print(body)
if content_type == "text/html":
# if it's HTML, create a new HTML file and open it in browser
folder_name = clean(subject)
if not os.path.isdir(folder_name):
# make a folder for this email (named after the subject)
os.mkdir(folder_name)
filename = "index.html"
filepath = os.path.join(folder_name, filename)
# write the file
open(filepath, "w").write(body)
# open in the default browser
webbrowser.open(filepath)
print("="*100)
# close the connection and logout
imap.close()
imap.logout()

Как удалить электронные письма в Python?
Для того чтобы удалять электронные письма, можно использовать вот этот код:

import imaplib
import email
from email.header import decode_header
# учетные данные
username = ""
password = "password"
# create an IMAP4 class with SSL
imap = imaplib.IMAP4_SSL("imap.gmail.com")
# authenticate
imap.login(username, password)
# select the mailbox I want to delete in
# if you want SPAM, use imap.select("SPAM") instead
imap.select("INBOX")
# поиск определенных писем по отправителю
status, messages = imap.search(None, "FROM", "")
# преобразовать сообщения в список адресов электронной почты
messages = messages[0].split(b' ')
try:
for mail in messages:
_, msg = imap.fetch(mail, "(RFC822)")
# вы можете удалить цикл for для повышения производительности, если у вас длинный список писем
# потому что он предназначен только для печати SUBJECT целевого электронного письма, которое нужно удалить
for response in msg:
if isinstance(response, tuple):
msg =
 
email.message_from_bytes(response[1])
# расшифровать тему письма
subject = decode_header(msg["Subject"])[0][0]
if isinstance(subject, bytes):
# if it's a bytes type, decode to str
subject = subject.decode()
print("Deleting", subject)
# отметить письмо как удаленное
imap.store(mail, "+FLAGS", "\\Deleted")
except:
print("Все удаленно")
# навсегда удалить письма, помеченные как удаленные
# из выбранного почтового ящика (в данном случае INBOX)
imap.expunge()
# закрыть почтовый ящик
imap.close()
# выйти из аккаунта
imap.logout()

Как отправлять электронные письма с Python?
Для того чтобы отправлять электронные письма, можно использовать вот этот код:

import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from bs4 import BeautifulSoup as bs
# ваши учетные данные
email = "uru07082000"
password = "password"
# электронная почта отправителя
FROM = ""
# адрес электронной почты получателя
TO = ""
# тема письма (тема)
subject = "Test"
# инициализируем сообщение, которое хотим отправить
msg = MIMEMultipart("alternative")
# установить адрес электронной почты отправителя
msg["From"] = FROM
# установить адрес электронной почты получателя
msg["To"] = TO
# задаем тему
msg["Subject"] = subject
# установить тело письма как HTML
html = """
Mail Python!
"""
# делаем текстовую версию HTML
text = bs(html, "html.parser").text
text_part = MIMEText(text, "plain")
html_part = MIMEText(html, "html")
# прикрепить тело письма к почтовому сообщению
# сначала прикрепите текстовую версию
msg.attach(text_part)
msg.attach(html_part)
print(msg.as_string())
def send_mail(email, password, FROM, TO, msg):
# инициализировать SMTP-сервер
server = smtplib.SMTP("smtp.gmail.com", 587)
# подключиться к SMTP-серверу в режиме TLS (безопасный) и отправить EHLO
server.starttls()
# войти в учетную запись, используя учетные данные
server.login(email, password)
# отправить электронное письмо
server.sendmail(FROM, TO, msg.as_string())
# завершить сеанс SMTP
server.quit()
send_mail(email, password, FROM, TO, msg)
Также можно делать рассылки с помощью этого кода:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from bs4 import BeautifulSoup as bs
to_list = ['', '']
def send_mail(email, password, FROM, TO, msg):
# инициализировать SMTP-сервер
server = smtplib.SMTP("smtp.gmail.com", 587)
# подключиться к SMTP-серверу в режиме TLS (безопасный) и отправить EHLO
server.starttls()
# войти в учетную запись, используя учетные данные
server.login(email, password)
# отправить электронное письмо
server.sendmail(FROM, TO, msg.as_string())
# завершить сеанс SMTP
server.quit()
for recipient in to_list:
# ваши учетные данные
email = ""
password = "password"
# электронная почта отправителя
FROM = ""
# адрес электронной почты получателя
TO = recipient
# тема письма (тема)
subject = "Прикол"
# инициализируем сообщение, которое хотим отправить
msg = MIMEMultipart("alternative")
# установить адрес электронной почты отправителя
msg["From"] = FROM
# установить адрес электронной почты получателя
msg["To"] = TO
# задаем тему
msg["Subject"] = subject
# установить тело письма как HTML
html = """
Рассылка - Пока!!!!!
"""
# делаем текстовую версию HTML
text = bs(html, "html.parser").text
text_part = MIMEText(text, "plain")
html_part = MIMEText(html, "html")
# прикрепить тело письма к почтовому сообщению
# сначала прикрепите текстовую версию
msg.attach(text_part)
msg.attach(html_part)
# отправить почту
send_mail(email, password, FROM, TO, msg)

Автоматизация входа в систему с помощью Selenium

Автоматизация процесса входа на какой-либо веб-сайт, используя программу, написанную на Python, очень удобна и практична в эксплуатации. Реализовывается это благодаря библиотеке Selenium WebDriver. Selenium WebDriver — это библиотека для управления браузером, которая поддерживает все основные браузеры и доступна для разных языков программирования, включая Python. И в данной работе я бы хотел использовать ее для автоматизированного входа на GitHub.
Первым делом, что нам необходимо сделать – это установить Selenium для Python, использую команду: pip3 install selenium. После этого, понадобится установить специфичный драйвер для браузера, которым мы хотим управлять. Лично я, буду использовать ChromeDriver, но вы можете использовать любой другой. Далее, необходимо открыть новый скрипт Python, инициализировать WebDriver и ввести свои учетные данные от GitHub:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
# Github credentials
username = "username"
password = "password"
# initialize the Chrome driver
driver = webdriver.Chrome("chromedriver")

После того, как мы загрузили и разархивировали драйвер, необходимо будет его поместить в текущий каталог, то есть, скачанный мною chromedriver.exe я помещаю в папку с проектом. Именно поэтому, я просто передаю его имя конструктору.
Поскольку мы заинтересованы в автоматизации входа в систему GitHub, то перейдем на страницу входа в Github и посмотрим на неё через кнопку f12 для того, чтобы найти её HTML элементы, а именно: идентификатор полей ввода логина и пароля, а также имя кнопки входа, необходимые для получения этих элементов в коде и их запрограммирования. Обратите внимание, что поле ввода имени пользователя/адреса электронной почты имеет id поля login_field, где поле ввода пароля имеет id password. Также кнопка отправки имеет имя commit. И приведенный ниже код переходит на страницу входа в Github, извлекает эти элементы, заполняет учетные данные и нажимает кнопку:

# перейти на страницу входа в github
driver.get("https://github.com/login")
# найти поле имени пользователя / электронной почты и отправить само имя пользователя в поле ввода
driver.find_element_by_id("login_field").send_keys(username)
# найти поле ввода пароля и также вставить пароль
driver.find_element_by_id("password").send_keys(password)
# нажмите кнопку входа в систему
driver.find_element_by_name("commit").click()
В данном коде, функция find_element_by_id() извлекает HTML элемент по его идентификатору, а метод send_keys() имитирует нажатие клавиш. Приведенный выше код заставит Chrome ввести электронное письмо и пароль, а затем нажать кнопку «Sign in».

Следующее, что нужно сделать, это определить, был ли наш вход в систему успешным. Для этого есть масса способов, но здесь мы попытаемся обнаружить ошибку при входе в систему. С помощью все той же консоли, которая вызывается клавишей f12, мы увидим, что при непрвильном вводе учетных данных, появляется новый элемент div HTML с классом «flash-error», который имеет текст «Incorrect username or password» («Неправильное имя пользователя или пароль»). Приведенный ниже код отвечает за ожидание загрузки страницы после входа в систему с помощью WebDriverWait() и проверяет наличие ошибки:

# ждем завершения состояния готовности
WebDriverWait(driver=driver, timeout=10).until(
lambda x: x.execute_script("return document.readyState === 'complete'")
)
error_message = "Incorrect username or password."
# получаем ошибки (если есть)
errors = driver.find_elements_by_class_name("flash-error")
# при необходимости распечатать ошибки
# для e в ошибках:
# print(e.text)
# если мы находим это сообщение об ошибке в составе error, значит вход не выполнен
if any(error_message in e.text for e in errors):
print("[!] Login failed")
else:
print("[+] Login successful")

Тут мы используем WebDriverWait, чтобы

дождаться завершения загрузки документа, метод execute_script() выполняет Javascript в браузере, код JS возвращает document.readyState === 'complete' возвращает True, если всё хорошо и False в противном случае.
В результате всех этих действий мы получаем очень удобную программу, которая упрощает нам жизнь. Например, мы написали какую-либо программу на Python и хотим ее выгрузить на наш GitHub. И раньше, чтобы это сделать, необходимо было заходить в браузер, переходить на сайт, вводить свои учетные данные и после этого уже загружать свой новый проект в репозиторий. Теперь же, достаточно просто запустить эту программу, и она все основные действия сделает за вас, вам останется лишь загрузить свой проект.

09.07.21

Девятый день практики
Последний день практики мы провели в уютной атмосфере, закончили очень быстро
В этот день мы навели не только порядок в архивах, но и сделали кабинет намного уютнее и красивее
Это был незабываемый опыт, с удовольствием повторила бы еще 🙂

08.07.21

Восьмой день практики
В этот раз были обсуждены планы на будущее и на последний день практики

07.07.21

Седьмой день практики
Седьмой день практики шел все также продуктивно, как предыдущие. На седьмой день мы сортировали курсовые, начин

06.07.21

Восьмой день практики
В этот день мы принялись за разбор контрольных работ нашего факультета, были утилизированы множество ненужных бумаг, и рассортированы отходы

05.07.21

Шестой день практики
На шестой день практики мы успешно выполняли свою работу, разбирая контрольные и другие работы бывших студентов. Слишком старые работы приходилось утилизировать