Знакомство с веб-технологиями
Как работают сайты в интернете?
Кратко: когда вы вбиваете адрес сервера в ваш браузер, браузер соединяется с этим сервером и отправляет ему запрос по протоколы HTTP (https://ru.wikipedia.org/wiki/HTTP). Это текстовый прикладной протокол поверх TCP/IP. В ответ, сервер присылает вашему браузеру HTML код страницы.
HTML - это язык разметки, который используется для оформления страниц в интернете. Например, он позволяет выделять в тексте заголовки, делать шрифт жирным или курсивным, вставлять абзацы и таблицы и многое другое. Идея HTML в помещение текста внутрь тэгов, которые определяют, каким будет этот текст.
Краткое знакомство:
- http://htmlbook.ru/samhtml/vvedenie-v-html
- https://www.w3schools.com/html/default.asp
- https://htmlacademy.ru/
Если HTML код на сервере лежит в виде файла, то такая страница называется статической, а если она генерируется кодом на python или PHP (или любом другом) прямо во время запроса - такая страница называется динамической.
Помимо HTML, на странице могут быть CSS стили и скрипты на JavaScript. CSS стили задают дизайн страницы (например, цвета и отступы), а JS позволяет сделать страницы интерактивными (всплывающие окна, вкладки, фоновое обновление страниц и тд.)
Некоторые определения
Веб-сервер
- устройство vs. программа
- задача — получать запросы от других компьютеров или программ (клиентов, clients) и отправлять запрошенные данные
- основная функция — размещение сайтов (website hosting)
Термины
- Запрос (request) — сообщение от агента, желающего получить или разместить информацию
- Ответ (response) — ответное сообщение сервера с кодом состояния и информацией (HTML, изображения, загружаемые файлы и т. п.)
- Протокол (protocol) — набор правил, по которым составляются запросы и ответы
- Сессия (session) — установка соединения между агентом и сервером и последующая серия запросов и ответов
- Гипертекст — множество текстов, организованных в виде графа при помощи гиперссылок
- Протокол HTTP (HyperText Transfer Protocol) — протокол для передачи гипертекстовых данных (обычно в виде HTML)
- URL (Uniform Resource Locator), веб-адрес ресурса — строка, представляющая собой уникальное имя, по которому можно найти в сети этот ресурс
Адресация
IP
- IP-адрес — (пока что) набор из 4 байт, присваиваемый каждому подключённому к сети устройству
- Некоторые IP-адреса уникальны, некоторые — нет (внутренние адреса в локальных сетях)
- Практически любой ресурс (например, сайт) можно получить по его IP-адресу (например, через браузер)
- Существуют зарезервированные адреса и диапазоны адресов, например,
127.0.0.1
— адрес данного устройства
Порт
- Каждый запрос обращается не просто к какому-то IP-адресу, а к некоторому порту на этом адресе
- Веб-сервер имеет 65 535 портов, пронумерованных начиная с 1
- Веб-сервер может прослушивать некоторые порты (listen to ports) и по-разному обрабатывать сообщения, поступившие на разные порты
- Если порт не прослушивается, сообщения на этот порт останутся без ответа
URL
http://www.example.com:1234/directory1/file1.html
протокол://доменное имя или IP-адрес:порт/адрес файла на сервере
- Порт указывать не обязательно: используются стандартные порты (HTTP — 80, FTP — 20 и т. п.)
- DNS (Domain Name Servers) — специальные сервера в сети, на которых хранятся таблицы соответствия между доменными именами и IP-адресами их серверов
HTML и скрипты
- страницы, содержимое (HTML-код) которых не изменяется, называются статическими (static)
- страницы, содержимое которых может быть разным в зависимости от введённых пользователем данных, времени, IP-адреса и т. п., называются динамическими (dynamic)
- динамические страницы создаются с помощью скриптов на стороне сервера (server side scripts), написанных, например, на PHP или Python
- скрипт порождает HTML и посылает его пользователю
- пользователь не видит кода скрипта, выполняющегося на сервере
- скрипт на стороне клиента (client side script) — вставка в HTML на каком-то языке программирования (например, JavaScript), позволяющая странице вести себя интерактивно
- код клиентских скриптов посылается клиенту сервером вместе с HTML и не выполняется на сервере
Питон и сайты
Написать сайт на питоне значит написать такую программу, которая может работать веб-сервером или использоваться веб-сервером для порождения HTML-кода веб-страниц. Для этого существует несколько модулей, например, Django и Flask
Веб-сервер на чистых сокетах
Для получения HTML кода страниц от сервера в интернете используется протокол HTTP. Это текстовый протокол, в котором после подключения к серверу клиент (браузер) должен отправить запрос с описанием того, что он хочет, а сервер в ответ посылает HTML код.
Давайте попробуем сделать совсем простой веб-сервер, используя только стандартные сокеты.
import socket
host = ''
port = 80
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((host, port))
sock.listen(1)
while True:
conn, caddr = sock.accept()
print ("Connection from: ", caddr)
req = conn.recv(1024).decode('utf-8')
print (req)
conn.sendall("""HTTP/1.0 200 OK
Content-Type: text/html
<html>
<head>
<title>Success</title>
</head>
<body>
Boo!
</body>
</html>
""".encode('utf-8'))
conn.close()
Попробуйте запустить его и в вашем любимой браузере перейти по адресу http://127.0.0.1
. Если все работает правильно вы увидите HTML страницу со словом Boo!
.
Код выше печатает в консоли код запроса, который пришел от клиента:
GET / HTTP/1.1
Host: 127.0.0.1:80
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
Как видите, это текстовое сообщения, в котором в первой строке указано, что посылается HTTP запрос GET / HTTP/1.1
, а далее указываются некоторые его параметры.
В ответе мы посылаем клиенту строки HTTP/1.0 200 OK
и Content-Type: text/html
, в которых указано, что страница найдена и ответ - это HTML код, а дальше (спустя одну пустую строку) отдаем ответ в виде HTML кода.
Flask - небольшой фреймворк для разработки веб-сервисов
Несмотря на то, что веб-сервер на питоне можно сделать простыми сокетами, обычно так не делают: приходится каждый раз самостоятельно описывать тонкости работы с протоколом, вместо того, чтобы просто писать на какой запрос как нужно овтетить.
Чтобы упростить эту задачу, программисты часто используются фрейворки - это библиотеки, которые упрощают разработку кода и задают некоторый удобный шаблон, как должна выглядеть программа. Например, для разработки веб-сервисов на питоне удобно использовать Flask - https://flask.palletsprojects.com/en/3.0.x/.
pip install flask
Например, код сервера, который мы писали выше на сокетах, на Flask будет выглядеть так:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<html><body>Boo!</body></html>'
app.run(debug=True, port=8080)
Чтобы увидеть результат, нужно в браузере зайти на адрес http://127.0.0.1:8080
.
PS: Я выбрал порт 8080, тк для выбора порта 80 программу нужно запускать от имени администратора (sudo python3 my_server.py
).
Подобно коду телеграм ботов, код на flask состоит из функций, каждая из которых отвечает на конкретный запрос пользователя. В декораторе @app.route('/')
указывается путь к странице, которую запросил пользователь, а вернуть функция должна html код, который нужно отправить пользователю.
Напримен, если помимо главной страницы (http://127.0.0.1:8080/
) нам понадобися страница http://127.0.0.1:8080/about
, код будет выглядеть следующим образом:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<html><body>Boo!</body></html>'
@app.route('/about')
def about():
return """
<html>
<body>
Это страница о сервисе!
</body>
</html>
"""
app.run(debug=True, port=8080)
PS1: В режиме отладки (debug=True
) переапускать программу после каждого изменения не трбуется.
PS2: Выше использован многострочный текст, в питоне для его обозначения вместо одинарных используются тройные кавычки.
Синтаксис HTML
Для описания внешнего вида страницы ипользуются HTML теги. Почти всегда теги идут в паре - открывающий и закрывающий (такая пара называется HTML элемент). Если открывающий тег <p>
, то закрывающий будет </p>
. Элементы можно вкладывать друг в друга или располагать рядом. В этом случае внешний элемент называется родителем (parent), а вложенный ребенком (child).
Важно: Теги закрываются по принципу стека: последний открылся - первый закрылся. Таким образом либо элемент находится полностью внутри второго элемента, либо они не пересекаются.
В любом HTML документе должны присутствовать теги <html>
, <head>
и <body>
.
В онлайн редакторах
<html>
и<head>
писать не нужно.
<html>
<head>
...
</head>
<body>
...
</body>
</html>
Рассмотрим приведенный выше пример HTML файла:
<html>
является главным тегом, внутри него находятся абсолютно все элементы на странице- внутри
<head>
располагается вспомогательная информация для браузера (например, заголовок страницы) - внутри
<body>
располагаются все блоки, которые будут видны на странице (например, текст)
Чтобы создать свою страницу сохраните файл с расширением
.html
и откройте его в браузере. Для этого нажмите на файл правой кнопкой мыши и выберитеОткрыть с помощью...
Теги HTML можно писать в любом регистре. Здесь и далее будет использоваться строчный вариант.
Для улучшения читаемости принято добавлять дополнительный отступ вложенным элементам.
Основные теги
Рассмотрим основные теги, с помощью которых совсем скоро вы сможете написать свой первый сайт.
Текст, заголовки, ссылки
До сих пор главным способом представления информации в интернете является текст, поэтому рассмотрим теги для создания заголовков, абзацев, ссылок и их позиционирования.
Тег | Описание |
---|---|
<p> </p> |
Абзац (от слова paragraph) |
<b> </b> |
Текст жирно выделенный (от слова bold) |
<s> </s> |
Зачеркнутый текст (от слова strikethrough) |
<i> </i> |
Текст выделенный курсивом (от слова italic) |
<h1> </h1> |
Заголовок (существуют 6 типов заголовков: <h1> самый большой, <h6> самый маленький) |
<br> |
Перевод строки (не требует закрывающего тега) |
<hr> |
Горизонтальная черта (не требует закрывающего тега) |
<a href="..."> </a> |
Ссылка, ведущая по адресу, указанному в кавычках |
Как говорилось ранее, теги можно вкладывать друг в друга, тем самым комбинируя эффекты, например, сделать абзац с жирной курсивной ссылкой.
<p>
<b><i><a href="http://ya.ru">Яндекс</a></i></b>
</p>
Атрибуты
Некоторые элементы обладают атрибутами - специальными свойствами, указываемыми в открывающем теге.
<a href="http://ya.ru" title="Перейти на Яндекс">Яндекс</a>
Атрибуты перечисляются через пробел, а их значения (в двойных кавычках) присваиваются через знак равно.
Картинки
Как бы не был хорошо написан текст, без картинок обойтись трудно. Для вставки изображений используется тег <img>
(сокращение от image). Закрывающий тег не требуется. Основными атрибутами для картинки являются:
src
задает путь к картинке (сокращение от source)width
задает ширину в пикселях (или процентах, если приписать знак процента)height
задает высоту аналогично ширинеalt
задает текст, отображаемый на месте картинки в случае невозможности загрузить картинку
<img src="http://mysite.com/img/example.jpg" height="640" width="480">
Если поместить картинку в тег <a>
, то при нажатии на нее будет происходить переход, как по ссылке.
Списки
Для структурирования информации удобно использовать списки. Существуют нумерованный (упорядоченный) список <ol>
(сокращение от ordered list) и неупорядоченный список <ul>
(сокращение от unordered list). Каждый пункт списка помещается в тег <li>
(сокращение от list item).
<ol>
<li>Пункт под номером 1</li>
<li>Пункт под номером 2</li>
<li>Пункт под номером 3</li>
<li>Пункт под номером 4</li>
</ol>
<ul>
<li>Просто пункт</li>
<li>Просто пункт</li>
<li>Просто пункт</li>
<li>Просто пункт</li>
</ul>
Как и другие элементы, списки можно вкладывать друг в друга, тем самым создавая подпункты пункта.
Таблицы
Еще эффективнее для структурирования информации можно использовать таблицы. Каждая таблица состоит тега таблицы <table>
, строк таблицы <tr>
(сокращение от table row), ячеек таблицы <td>
(сокращение от table data) или ячеек-заголовков <th>
(сокращение от table header). Строки вложены в таблицу, а ячейки вложены в строки.
<table border="1" cellspacing="0">
<tr>
<th>Столбец 1</th>
<th>Столбец 2</th>
<th>Столбец 3</th>
</tr>
<tr>
<td>1-1</td>
<td>1-2</td>
<td>1-3</td>
</tr>
<tr>
<td>2-1</td>
<td>2-2</td>
<td>2-3</td>
</tr>
<tr>
<td>3-1</td>
<td>3-2</td>
<td>3-3</td>
</tr>
</table>
В этом примере атрибут border
задает толщину границы между ячейками (по-умолчанию ее нет), а атрибут cellspacing
задает расстояние между ячейками (значение 0 заставялет слипнуться границы ячеек, тем самым избавиться от двойных границ).
Для растягивания ячейки <td>
направо используется атрибут colspan
, а для растягивания вниз rowspan
.
<table border="1" cellspacing="0">
<tr>
<th>Столбец 1</th>
<th>Столбец 2</th>
<th>Столбец 3</th>
</tr>
<tr>
<td>1-1</td>
<td>1-2</td>
<td rowspan="2">1-3 && 2-3</td>
</tr>
<tr>
<td colspan="2">2-1 && 2-2</td>
</tr>
<tr>
<td colspan="3">3-1 && 3-2 && 3-3</td>
</tr>
</table>
Тег <head>
Внутри тега head
помещают некоторые технические теги. Например, теги с информацией о языке странице, ее кодировке, теги, в которых мы загружаем стили.
На данный момент нам интересны только два тега.
<title>Title</title>
задает заголовок страницы, отображаемый в названии вкладки<meta charset="utf-8">
сообщает браузеру, что HTML файл имеет кодировкуutf-8
. Таким образом сохранив файл в такой же кодировке (современные редакторы используют ее по умолчанию) удастся избежать "крокозябр".
Статические файлы и Flask
Если вам нужно разместить на вашем сайте обычный файл, например, картинку, то вам нужно содать папку static
в папке с вашим проекто и разместить его там.
Например, если мы положим картинку image.jpg
в папку static
рядом с my-server.py
, то вставить ее можно так:
<img src="/static/image.jpg" />