├── .gitignore
├── Homeworks
├── AdditionalHW.md
├── Final_project.md
├── HW1.md
├── HW2.md
├── HW5.md
├── HW6.md
├── HW7.md
├── PapersHW.md
├── Project.ipynb
└── QuestionnaireHW.md
├── LICENSE
├── Lessons
├── Flask
│ ├── 10. Flask (2) .ipynb
│ ├── 9. Flask (1).ipynb
│ ├── flask_example
│ │ ├── my_app.py
│ │ └── templates
│ │ │ ├── answer.html
│ │ │ ├── books.html
│ │ │ ├── index.html
│ │ │ ├── question.html
│ │ │ └── thanks.html
│ └── langcodes.csv
├── Heroku и командная строка
│ ├── 13a. Heroku.md
│ ├── 13b. Командная строка UNIX, логин на сервере.md
│ └── cmd cheatsheet.md
├── JSON
│ ├── 3. JSON.ipynb
│ └── data.json
├── Markdown и git
│ ├── 1. Intro.ipynb
│ ├── DS_Store-gitignore.md
│ ├── Markdown.md
│ ├── cmd cheatsheet.md
│ └── deadline.jpg
├── Matplotlib
│ ├── 11. Matplotlib.ipynb
│ └── nanai-vowels.csv
├── Telegram-боты
│ ├── TelegramBot1.ipynb
│ ├── TelegramBot2.ipynb
│ ├── TelegramBot3.ipynb
│ ├── bot_example
│ │ ├── bot.py
│ │ ├── results.csv
│ │ └── reviews.csv
│ ├── dal_proverbs.csv
│ └── reviews.csv
├── Twitter API
│ └── Tweepy.ipynb
├── VK API
│ ├── 14. VK API (1).ipynb
│ ├── 15. VK API (2).ipynb
│ ├── comment.jpg
│ └── post_cloud.png
├── Word2vec
│ ├── liza_lem.txt
│ ├── ru_analogy_tagged.txt
│ └── word2vec.ipynb
├── Базы данных
│ └── 12. Базы данных.ipynb
├── Веб-запросы и формы
│ └── 8. Запросы и формы.ipynb
├── Графы
│ └── Графы, networkx.ipynb
├── Интерактивные визуализации
│ └── Интерактивные графики и карты в вебе.md
├── Краулеры и парсинг веб-документов
│ ├── 4a. Urllib.ipynb
│ ├── 4b. Краулеры.ipynb
│ └── lxml_bs4.ipynb
├── Морфологический анализ
│ ├── 6. Mystem.md
│ ├── 7. pymorphy2, pymystem3.ipynb
│ └── rus_stopwords.txt
└── Структуры данных
│ ├── 2. Структуры данных.ipynb
│ ├── KILI_seminar2_datatypes.pdf
│ └── kilipractice.py
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
106 | conf.py
--------------------------------------------------------------------------------
/Homeworks/AdditionalHW.md:
--------------------------------------------------------------------------------
1 | # pymystem3 & pymorphy2
2 | ## Необязательное задание
3 |
4 | *Задание дает возможность поднять накопленную оценку. У тех, кто его сделает, накопленная за д/з будет разделена на 8, а у тех, кто не сделает, — на 7 (по количеству выполненных работ).*
5 |
6 | Написать flask-приложение, с которым можно разговаривать: пользователь пишет ему реплику, а оно отвечает предложением, в котором все слова заменены на какие-то случайные другие слова той же части речи и с теми же грамматическими характеристиками. Предложение-ответ должно быть согласованным. Ответ должен появляться на той же странице, где пользователь вводит фразу.
7 |
8 | Например, на фразу "Мама мыла раму" программа может ответить "Девочка пела песню".
9 |
10 | Для такой программы вам понадобится большой список русских слов:
11 |
12 | * можно взять список словоформ с сайта НКРЯ - http://ruscorpora.ru/corpora-freq.html
13 | * можно взять просто любой большой текст, вытащить из него слова и использовать их
14 |
15 | Из этого списка вам нужен только список разных лемм разных частей речи, и затем нужно будет использовать функции `parse` и `inflect` из `pymorphy2`.
16 |
17 | **NB! Задание выполняется в виде обычного .py скрипта (или нескольких скриптов).**
18 |
19 | ## Критерии оценки
20 |
21 | |Балл|Критерий|
22 | |----|--------|
23 | |1|Программа запускается и оформлена по PEP8. Соответствие PEP8 можно проверить с помощью команды `pycodestyle my_script_name.py` в командной строке.|
24 | |1|Список слов взят с сайта НКРЯ или сопоставим по объему (т.е. список из 100-200 слов не подойдет).|
25 | |2|Программа генерирует ответ. Ответ выводится на той же странице, что и форма ввода, форма ввода никуда не исчезает. |
26 | |2|Все слова в ответе заменены на слова с такими же грамматическими характеристиками. Слова выбираются случайным образом. Слова, введенные пользователем, не используются в ответе.|
27 | |2|Ответ программы (будь то предложение или просто словосочетание) грамматически согласован.|
28 | |2|Сайт оформлен с помощью `bootstrap`|
29 |
30 | ## Дедлайн
31 |
32 | |Группа|Дедлайн|
33 | |----|--------|
34 | |1|15 мая, 10.00|
35 | |2|13 мая, 10.00|
36 | |3|15 мая, 10.00|
37 | |4|24 мая, 10.00|
38 |
--------------------------------------------------------------------------------
/Homeworks/Final_project.md:
--------------------------------------------------------------------------------
1 |
2 | ## Заготовки тем для финальных проектов
3 |
4 | **Свою тему нужно будет вписать [вот в эту табличку](https://docs.google.com/spreadsheets/d/18KH0d2gKIFB5Ddl3YYPbkYpyj0Ob_qSYpINiE77VHyg/edit?usp=sharing).**
5 |
6 | Код проекта должен быть выложен в репозиторий в папку `FinalProject`, а также на `heroku`. Т.е. веб-сервис или телеграм-бот должен работать вне зависимости от того, запущен ли код на вашем/чьем-то другом компьютере. Ссылка на ваше herokuapp должна быть в `README` в папке с проектом.
7 |
8 |
9 | №|Шаблон|Описание|Что выбрать самостоятельно
10 | -|------|--------------------------|----
11 | 1.|«Гарри Поттер и...»|Веб-сервис/телеграм-бот, который присылает пользователю фразы, сгенерированные с помощью марковской цепи.|Данные, на которых будет обучаться марковская цепь, сходные по объему со [всеми книгами о Гарри Поттере](https://www.dropbox.com/s/gg62ggme0hi7zqk/%D0%94%D0%B6%D0%BE%D0%B0%D0%BD%20%D0%A0%D0%BE%D1%83%D0%BB%D0%B8%D0%BD%D0%B3.%20%D0%93%D0%B0%D1%80%D1%80%D0%B8%20%D0%9F%D0%BE%D1%82%D1%82%D0%B5%D1%80%20%282018%29.fb2?dl=0)
12 | 2.|Анекдоты|Веб-сервис/телеграм-бот, который по заданному персонажу находит в корпусе анекдоты о нем|Это тема для одного человека
13 | 3.|Толстой или компьютер?|Веб-сервис/телеграм-бот, который играет с пользователем в игру: предлагает угадать, оригинальное ли перед ним предложение какого-либо автора или сгенерированное компьютером с помощью word2vec. В конце показывает результат пользователя и статистику правильных ответов.|Автора, в произведениях которого будут заменяться слова.
14 | 4.|Пушкин каждый день|Веб-сервис/телеграм-бот, который в ответ на реплику пользователя отвечает строчкой из какого-либо русского поэта в рифму|Можно сделать либо веб-сервис, либо телеграм-бота; можно взять как стихи какого-нибудь одного поэта, так и нескольких (лучше всего использовать поэтический корпус НКРЯ
15 | 5.|Бот-рифмоплет|Веб-сервис/телеграм-бот, который генерирует стихотворение со словом, которые ввел пользователь|Можно сделать либо веб-сервис, либо телеграм-бота; можно выбрать формат стихов: пирожки, порошки, рифмованные двустишия, хайку...
16 | 6.|Новостные тренды|Веб-сервис, которое периодически скачивает новости с любого сайта, где они есть (от "Известий" до главной страницы Школы лингвистики) и строит график совместной встречаемости полнозначных слов в окне 3.| Новостной сайт
17 | 7.|Все, что вы хотели знать о...|Веб-сервис, которое по id пользователя/сообщества Вконтакте выводит график самых частотных полнозначных слов на заданнный период времени, а также статистику по комментаторам: город, пол, возраст|Это тема для одного человека
18 | 8.|«...» Вконтакте|Веб-сервис, который обращается к заданному набору сообществ Вконтакте на определенную тему, скачивает последние 300 записей и строит графики частотности ключевых слов по этой тематике (их набор, 10-20 штук, вы определяете самостоятельно). Для каждого сообщества должен быть отдельный график, + график-сравнение по всем сообществам|Тематику, набор сообществ вк по этой тематике и ключевые слова
19 | 9.|The PenPal|Веб-сервис, где пользователь вводит текст, а программа автоматически ему отвечает. Необходимо обеспечить определённую степень связности между тем, что пишет пользователь, и тем, что отвечает программа. Ожидается, что будут комментарии или отдельный текстовый файл, объясняющий, как обеспечивается связность. Для этого нужно использовать пройденные темы (в любых комбинациях): регулярные выражения, морфологический анализ, word2vec, VK API и т.д. |Выбрать "персону" программы: она может сочувствовать, ругать, давать советы и т.п.
20 | 10.|Fieldwork Crowdsourcing|Веб-сервис, который позволяет носителям (малых) языков и лингвистам, занимающимся этими языками, добавлять тексты и другие материалы (можно выбрать жестовый язык, тогда добавляться будут фото и видео). Программа создаёт базу данных, в которой хранятся тексты (видео, фото), социолингвистическая информация о добавивших тексты (видео, фото). Есть страница поиска (по словам, по социолингвистическим параметрам); есть страница, отражающая статистику по социолингвистическим параметрам.| Выбрать язык (стартовые материалы по языку можно выкачать из интернета), выбрать конкретные параметры, которые веб-сервис будет позволять добавлять.|
21 | 11.|Своя тема|Необходимо использовать как минимум 3 пройденных за год темы (в любых комбинациях): например, VK API, matplotlib, морфологический анализ; flask, word2vec, графы и т.д.|
22 |
23 |
--------------------------------------------------------------------------------
/Homeworks/HW1.md:
--------------------------------------------------------------------------------
1 | ## Домашнее задание №1
2 | ### Игра "Виселица"
3 |
4 | - Придумайте любые 3 темы (например, "лингвистические термины", "фамилии актеров", "блюда грузинской кухни") и составьте по каждой из них список из 10-15 слов, лучше длинных. Списки слов по разным темам должны быть сохранены в отдельных txt-файлах.
5 |
6 | - При запуске программа должна предлагать пользователю выбрать одну из трех тем и загружать список слов, соответствующий выбору. Далее она должна случайным образом выбирать из списка и говорить пользователю что-то на подобии "У вас есть N попыток, чтобы угадать слово из X букв" и выводить строчку из _ по количеству букв в слове, разделенных пробелами. Количество попыток нужно выбрать самостоятельно, оно должно всегда быть одинаковым.
7 |
8 | - Если пользователь угадал букву, то программа должна заменять _ в соответствующем месте на угаданную букву
9 |
10 | - Программа должна выдавать разные сообщения в зависимости от того, угадал пользователь букву или нет, а также если он уже вводил эту букву или если введенный символ — не буква. Чувствительность к регистру не нужна!
11 |
12 | - Если названной буквы нет в слове, то программа должна рисовать деталь человечка. Обратите внимание, что количество деталей должно быть равно количеству попыток! Как будет выглядеть картинка, выбирайте сами
13 |
14 | - Код должен быть оформлен в виде функций с соблюдением правил PEP8. Не забывайте писать комментарии к функциям!
15 |
16 | **Примечание №1**: Код должен быть оформлен в ipython notebook!
17 |
18 | **Примечание №2**: Для ввода обязательно используйте функцию `input()`, что позволит получить строку ввода.
19 |
20 | **Примечание №3**: Отдельным одним баллом будет оценено умение программы согласовывать числительные с существительными, то есть выводить сообщения не "Осталось попыток: 5", а "Осталось 5 попыток, осталась 1 попытка" и т.п.
21 |
22 |
23 |
Балл
Критерий
24 |
1
Созданы текстовые файлы со словами
25 |
1
Программа запускается и оформлена по PEP8
26 |
1
Программа разделена на функции
27 |
2
Программа загадывает случайное слово из выбранной категории и правильно указывает, есть ли в нем буква, введенная пользователем
28 |
2
Программа умеет выводит нижние подчеркивания вместо неотгаданных букв
29 |
2
Программа корректно обрабытвает ошибочный ввод пользователя (как неправильно угаданная буква, так и некорректный символ), выводит число попыток и предлагает начать игру заново
30 |
1
Программа рисует детали человечка
31 |
1
Бонусный балл. Программа умеет склонять слово "попытка"
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Homeworks/HW2.md:
--------------------------------------------------------------------------------
1 | ## Домашнее задание №2
2 |
3 | Написать программу, которая получает на вход список пользователей гитхаба и умеет делать следующее:
4 |
5 | 1. Выбрать какого-то одного пользователя из полученного списка и распечатать список его репозиториев (name) и их описания (description). Выбор пользователя должен осуществляться с помощью ввода с клавиатуры (функция `input()`).
6 | 2. Распечатать список языков (language) выбранного пользователя и количество репозиториев, в котором они используются.
7 | 3. Узнать, у кого из пользователей в списке больше всего репозиториев.
8 | 4. Узнать, какой язык самый популярный среди пользователей списка.
9 | 5. Узнать, у кого из пользователей списка больше всего фолловеров? (фолловеров можно достать по ссылке `https://api.github.com/users/username/followers`, где вместо username -- имя пользователя)
10 |
11 | **Подсказка №1**. Для каждой из перечисленных операций нужно написать свою функцию. Каждая из них потом должна быть вызвана в функции `main()`, которой и передается список пользователей.
12 |
13 | **Подсказка №2**. В выводе каждая операция должна сопровождаться распространенным текстовым комментарием (вспоминайте форматирование строк!). Выглядеть это должно *примерно* так:
14 |
15 | Вы выбрали пользователя githubuser.
16 |
17 | Вот список его репозиториев:
18 | name1: description1,
19 | name2: description2,
20 | name3: description3.
21 |
22 | Пользователь githubuser пишет на JavaScript и C#.
23 |
24 | Язык JavaScript используется в репозитории name1 и name2, язык C# используется в репозитории name3.
25 |
26 | Из списка githubuser, githubuser1, githubuser2, githubuser3 больше всего репозиториев у пользователя githubuser2.
27 |
28 | Самый популярный язык среди пользователей из списка githubuser, githubuser1, githubuser2, githubuser3 -- JavaScript.
29 |
30 | Больше всего подписчиков у пользователя githubuser3.
31 |
32 |
33 | Тренироваться можно, например, на следующих 20 (не)случайных юзерах гитхаба: `elmiram, maryszmary, lizaku, nevmenandr, ancatmara, roctbb, akutuzov, agricolamz, lehkost, kylepjohnson, mikekestemont, demidovakatya, shwars, JelteF, timgraham, arogozhnikov, jasny, bcongdon, whyisjake, gvanrossum`.
34 |
35 | ### Критерии оценки
36 |
37 |
38 |
Балл
Критерий
39 |
1
Программа запускается и оформлена по PEP8
40 |
1
Программа разделена на функции
41 |
1
Программа умеет выбирать пользователя из заданного списка и распечатывать список его репозиториев с описаниями
42 |
1
Имя пользователя вводится с клавиатуры, при этом программа умеет ругаться, если введено что-то кроме имен пользователей из имеющегося списка, и просит в таком случае повторить попытку ввода
43 |
1
Программа умеет распечатывать список языков пользователя и количество репозиториев, в которых они используются
44 |
1
Программа умеет узнавать, у кого из пользователей больше всего репозиториев
45 |
1
Программа умеет узнавать, у кого из пользователей больше всего подписчиков
46 |
2
Программа умеет узнавать, какой язык самый популярный среди пользователей списка
47 |
1
Грамотно, с использованием форматирования строк оформлен вывод
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Homeworks/HW5.md:
--------------------------------------------------------------------------------
1 | ## Поисковая система для корпуса
2 |
3 | В этом задании вам нужно будет написать свой "Яндекс", который будет искать информацию в ранее собранном вами корпусе газеты из [третьго ДЗ](https://github.com/ancatmara/learnpython2018/blob/master/Homeworks/Project.ipynb).
4 |
5 | Для этого вам потребуется:
6 |
7 | 1. Придумать структуру базы данных и добавить в нее названия статей, их тексты, очищенные от тегов и прочего мусора (те, что лежат у вас в папке `plain` в третьем ДЗ), лемматизированные тексты (те, что лежат в папке `mystem-plain`) и ссылки на эти статьи на сайте вашей газеты. По желанию можно добавить в базу и другие метаданные: дату, автора и т.д.
8 | 2. Создать веб-сервис, в котором можно будет вбить произвольную фразу и получить ссылки на материалы, где она встречается, и кусочек страницы с ней. Т.е. на странице результатов поиска должен выводиться список всех статей, в тексте которых нашлось заданное слово / фраза. Каждый элемент списка -- это ссылка на эту статью на сайте и кусочек текста статьи (того, что лежит в вашей базе данных), содержащий запрос. Размер выводимого кусочка статьи -- на ваше усмотрение, рекомендуемая длина -- 250-500 символов.
9 | 3. На запрос по любой форме слова должны выводиться статьи, где это слово встречается в любой форме, а не только в этой. Например, вы вводите "котик" и получаете статьи со словами "котикам", "котика", "котику" и т.д. Ровно такая же выдача должна получиться и по запросу "котиков", "котиками" и т.д.
10 |
11 | Результаты поиска желательно выводить на главной странице. Если для них создана отдельная страница, то поле для ввода поискового запроса должно быть и там.
12 |
13 | В качестве СУБД рекомендуем использовать SQLite.
14 |
15 | ### Критерии
16 |
17 | |Балл|Критерий|
18 | |----|--------|
19 | |1|Программа запускается и оформлена по PEP8. Соответствие PEP8 можно проверить с помощью команды `pycodestyle my_script_name.py` в командной строке.|
20 | |1|Создана структура базы данных, удовлетворяющая требованиям задачи.|
21 | |2|Выполнен перенос всех необходимых данных в БД (названия статей, ссылки, обычные и лемматизированные тексты).|
22 | |1|Создано фласк-приложение с формой поиска на главной странице|
23 | |2|При отправке запроса через форму поиска выдаются ссылки на статьи из базы данных (хотя бы какие-то - 1 балл, все нужные данные из базы со словом из запроса в любых формах - 2 балла).|
24 | |2|Помимо ссылок и названий статей на странице отображается кусок страницы, в котором был найден текст запроса (как в Яндексе, лемматизированное описание - 1 балл, исходный текст - 2 балла).|
25 | |1|Постраничное отображение результатов поиска (как в Яндексе).|
26 | |1|**Бонусный балл** за оформление сайта с помощью bootstrap|
27 |
28 | **NB!** Это задание, как и предыдущее, лучше сдавать в виде обычного .py скрипта (а не тетрадки).
29 |
30 | **NB!** Если Вы не сделали задание 3, то создайте базу данных с нуля.
31 |
--------------------------------------------------------------------------------
/Homeworks/HW6.md:
--------------------------------------------------------------------------------
1 | # Домашнее задание №6
2 | ## VK API
3 |
4 | В домашнем задании вам нужно написать программу, которая обращается к открытому (то есть такому, чтобы для просмотра контента не нужна была авторизация) сообществу Вконтакте, выкачивает посты со стены и комментарии к ним. Сообщество можно выбрать любое, но постарайтесь не повторяться!
5 |
6 | Выберите сообщество поживее, чтобы там было много постов и много комментариев к ним. Посты должны содержать текст, и желательно не одну строчку, чтобы было, что исследовать. Обязательное условие: программа должна уметь скачивать со стены больше, чем 100 постов, и больше, чем 100 комментариев к посту (если их действительно больше 100). Кроме выкачивания нужно сделать следующее:
7 |
8 | * Посчитайте длину каждого поста и каждого комментария в словах.
9 | * Создайте график, описывающий, как длина поста соотносится со средней длиной комментариев.
10 | * Помимо выкачивания постов и комментариев, программа должна смотреть в профиль пользователя, который написал пост или сделал комментарий, и узнавать о нём социолингвистическую информацию: например, возраст и город (если они указаны). В таком случае, название города по его id можно узнать [средствами API](https://vk.com/dev/database.getCitiesById), а возраст нужно уметь вычислять. Обратите внимание, что разные поля в описании профиля ведут себя по-разному, для каждого нужно обязательно посмотреть документацию!
11 | * Постройте графики зависимости средней длины поста и средней длины комментария от различных социолингвистических параметров.
12 |
13 | **NB!** Для графиков, описывающих среднюю длину поста и комментария (в словах), нужно выбрать 4 каких-нибудь **разных** параметра: город, возраст, наличие фото, средняя длина описания в поле "о себе", вуз, количество указанных в профиле учебных заведений, количество друзей, количество языков и т.п. Два из этих параметров нужно использовать для построения графиков зависимости длины поста, другие два — для комментария. Т.е. всего в этом пункте 4 графика.
14 |
15 | Допустим, вы выбрали какой-нибудь паблик, где все посты публикуются от имени сообщества. Тогда можно построить графики зависимости средней длины поста, напимер, от месяца публикации и от года публикации (потому что об авторе нам тут сложно что-то узнать, а даже если и можно — он один, и это неинтересно). А комментаторов много, поэтому здесь можно использовать социолингвистическую информацию и построить графики зависимости длины комментария, например, от возраста и города. Или от пола и наличия фотографии в профиле. Или от пола и учебного заведения. Или от количества языков и средней длины "о себе". И так далее — простор для фантазии почти безграничен.
16 |
17 | Хотя бы 2 параметра должны быть информацией из профиля пользователя (т.е. если у вас все 4 графика, например, про время — число, месяц, год и день недели публикации — то так не пойдет, т.к. программа должна уметь доставать информацию из профиля автора).
18 |
19 | * Постройте график частотности для топ 20-30 слов, удалив перед этим стоп-слова. Проделайте это сначала с нелемматизированными текстами, а потом с лемматизированными (для лемматизации можно использовать pymystem pymorphy, на ваш вкус). Сильно ли отличаются эти графики? По желанию можно написать краткий анализ различий из 3-5 предложений. Можно построить не только диаграмму, но и облако слов.
20 | * Всего у вас должно получиться 7 графиков. Оформить грайфики можно как угодно, но главное, чтобы это было не оформление по умолчанию! Т.е. что-то в стиле нужно изменить самостоятельно. Также на графиках обязательно должен быть заголовок, подписи осей и подписи делений (например, в случае с городами подписями по оси Х будут названия городов). Картинки с графиками должны быть сохранены отдельными файлами в репозитории (а не только отображаться в тетрадке).
21 | * Выложите скачанные тексты: как и в случае с газетным корпусом, нужно выкладывать **не** на github, а в какое-нибудь облако, а ссылку на корпус добавить в readme.
22 | * Формат корпуса: должно быть выложено два файла в plain text, один с оригинальными текстами, другой с лемматизированными. Порядок постов и коментариев неважен. Объем корпуса: > 100 постов с комментариями (т.е. начиная от 101 до бесконечности). Если к какому-то из постов написано больше 100 комментариев, то все они должны быть выкачаны.
23 |
24 | **NB! Задание выполняется в ipynb-тетрадке с понятным названием (скажем, HW6_VK). Кроме того, обязательно должна быть ссылка на корпус! Без соблюдения этих двух условий задание не проверяется!**
25 |
26 | ## Критерии оценки
27 |
28 | |Балл|Критерий|
29 | |----|--------|
30 | |1|Программа запускается и оформлена по PEP8. Соответствие PEP8 можно проверить с помощью команды `pycodestyle my_script_name.py` в командной строке.|
31 | |2|Программа умеет выкачивать посты и комментариии (больше 100 постов и больше 100 комментариев к посту).|
32 | |1|Посчитана средняя длина поста и комментария в словах и построены соответствующие графики.|
33 | |1|Программа умеет доставать из профиля пользователя параметры №1 и №2 для графиков про среднюю длину **поста** (например, город с названием и возраст). В случае пабликов можно брать параметры не из профиля автора (например, год и день недели публикации поста).|
34 | |1|Построены графики зависимости средней длины поста от этих двух параметров, оформленные согласно требованиям. Графики со стандартными настройками без подписей — 0.5 балла.|
35 | |1|Программа умеет доставать из профиля пользователя параметры №3 и №4 для графиков про среднюю длину **комментария**.|
36 | |1|Построены графики зависимости средней длины поста от этих двух параметров, оформленные согласно требованиям. Графики со стандартными настройками без подписей — 0.5 балла.|
37 | |1|Построен график частотности для топ 20-30 слов по нелемматизированным текстам. График со стандартными настройками без подписей — 0.5 балла.|
38 | |1|Построен график частотности для топ 20-30 слов по лемматизированным текстам. График со стандартными настройками без подписей — 0.5 балла.|
39 | |**1**|**Бонусный балл.** Построено облако слов для топ 20-30 слов по лемматизированным текстам.|
40 | |**4**|**Бонусный балл.** Более сложная структура корпуса: сохранены не только тексты, но информация о пользователях, написавших тот или иной пост (id, город, возраст, пол, имя и далее по желанию), id поста/комментария и связь комментариев с постами. Можно сделать это в виде базы данных, можно просто в csv-таблице. В случае с БД за это задание дается 4 балла, в случае с таблицей — 3 балла.|
41 |
42 | ## Дедлайн
43 |
44 | |Группа|Дедлайн|
45 | |----|--------|
46 | |1|4 мая, 23.59|
47 | |2|28 апреля, 23.59|
48 | |3|4 мая, 23.59|
49 | |4||
50 |
--------------------------------------------------------------------------------
/Homeworks/HW7.md:
--------------------------------------------------------------------------------
1 | # ДЗ по графам и word2vec
2 |
3 | Ваша задача построить сеть для произвольного [семантического поля](https://www.krugosvet.ru/enc/gumanitarnye_nauki/lingvistika/SEMANTICHESKOE_POLE.html), где узлами будут слова, а ребрами наличие косинусного расстояния ≥0.5 в word2vec-модели (можно взять любую). Алгоритм работы следующий:
4 |
5 | 1. Выберите какое-нибудь семантическое поле, например, "транспорт", "глаголы говорения" и т.п. и в качестве первого узла или нескольких первых узлов возьмите любые слова из этого поля. Слова должны быть одной части речи!
6 | 2. Найдите соседей узла (узлов), заданного вами в качестве отправной точки, отфильтруйте их по значению косинусной близости и добавьте в граф.
7 | 3. Найдите соседей узлов, добавленных на предыдущем этапе, отфильтруйте их по значению косинусной близости и добавьте в граф.
8 | 4. Вычислите самые центральные узлы графа по degree centrality, betweenness centrality, closeness centrality и eigencentrality.
9 | 5. Вычислите плотность графа, его диаметр, радиус, коэффициент кластеризации и коэффициент ассортативности.
10 | 6. Попробуйте разделить граф на сообщества (можно выбрать любой алгоритм) и интерпретировать эти сообщества. Интерпретацию нужно написать в отдельной текстовой ячейке после кода, разбивающего граф на сообщества, или после визуализации графа.
11 | 7. Визуализируйте граф. Размер и цвет узлов должен соответствовать каким-то параметрам — например, размер может показывать центральность по любой из метрик, а цвет — разбиение на сообщества. Выбранные параметры должны быть указаны либо в комментариях к коду, либо в отдельной текстовой ячейке с описанием графа. Узлы должны быть подписаны.
12 |
13 | **NB! Задание выполняется в виде .ipynb-тетрадки. Однако, если вы решите делать веб-приложение на бонусный балл, необходимо сдать обычный .py скрипт (или несколько скриптов).**
14 |
15 | ## Критерии оценки
16 |
17 | |Балл|Критерий|
18 | |----|--------|
19 | |1|Программа запускается и оформлена по PEP8. Соответствие PEP8 можно проверить с помощью команды `pycodestyle my_script_name.py` в командной строке.|
20 | |2|Строится граф для какого либо семантического поля. Находятся соседи первого и второго порядка для изначально заданного узла (узлов).|
21 | |1|В граф добавляются только узлы, имеющие косинусную близость **≥0.5** к любому из уже имеющихся|
22 | |1|Реализована фильтрация по частям речи: узлами являются только существительные, только глаголы и т.п.|
23 | |1|Рассчитана центральность узлов графа по метрикам, указанным в п.4.|
24 | |1|Рассчитано значение метрик, указанных в п.5.|
25 | |1|Граф разбит на сообщества, есть краткая интерпретация.|
26 | |1|Граф визуализирован|
27 | |1|Внешний вид графа задан в соответствии с п.7|
28 | |5|**Бонусный балл.** Задание оформлено в виде веб-приложения, где пользователь может ввести любое слово в качестве начального узла и получить картинку с соответствующим графом и все статистики по нему (те, что указаны в задании + количество узлов и ребер).|
29 |
30 |
31 |
32 | ## Дедлайн
33 |
34 | |Группа|Дедлайн|
35 | |----|--------|
36 | |1|7 июня 10:00|
37 | |2|10 июня 10.00|
38 | |3|7 июня 10:00|
39 | |4|3 июня 10:00|
40 |
--------------------------------------------------------------------------------
/Homeworks/PapersHW.md:
--------------------------------------------------------------------------------
1 | # Собери корпус из газет
2 |
3 | ## Про проект
4 | 27-го октября (в 9:00), в репозитории должен лежать готовый код, который умеет делать всё, что перечислено ниже, а также в файле Readme.md в папке с проектом должна находиться ссылка на скачанные и обработанные файлы вашей газеты, лежащие **одним архивом** на Яндекс.Диске, Google Drive, Облаке@Мэйл.ру или на чём угодно подобном (но, пожалуйста, не надо заливать эти архивы на гитхаб).
5 |
6 | При этом
7 |
8 | 1. Общий объём скачанных текстов должен быть не меньше 100 тыс. слов.
9 | 2. В именах файлов не должно быть не-ascii символов (убираем их из url - [stackoverflow](https://stackoverflow.com/questions/4389572/how-to-fetch-a-non-ascii-url-with-python-urlopen)).
10 | 3. Структура каталогов, в которых хранятся файлы, должна быть следующей: корень/год/месяц/файлы с материалами за этот месяц
11 | 4. В корне также должна лежать csv-таблица с такими полями (разделитель - знак табуляции):
12 |
13 | ```
14 | path author sex birthday header created sphere genre_fi type topic chronotop style audience_age audience_level audience_size source publication publisher publ_year medium country region language
15 | ```
16 |
17 | Имена полей означают следующее:
18 |
19 | **path** -- это путь к чистому неразмеченному файлу со статьёй,
20 | **author** -- имя автора, если его можно достать со страницы (и вообще если оно есть),
21 | **sex** -- поле оставить пустым,
22 | **birthday** -- оставить пустым
23 | **header** -- название статьи
24 | **created** -- дата в формате 07.01.2012 (день.месяц.год)
25 | **sphere** -- слово "публицистика"
26 | **genre_fi** -- оставить пустым
27 | **type** -- оставить пустым
28 | **topic** -- категория, если мы её можем найти на странице со статьёй
29 | **chronotop** -- оставить пустым
30 | **style** -- слово "нейтральный"
31 | **audience_age** -- слово "н-возраст"
32 | **audience_level** -- слово "н-уровень"
33 | **audience_size** -- "районная", если газета районная, "республиканская", если газета республиканская, "городская" -- если городская
34 | **source** -- URL, откуда статья была скачана
35 | **publication** -- название газеты
36 | **publisher** -- оставить пустой
37 | **publ_year** -- год публикации
38 | **medium** -- слово "газета"
39 | **country** -- слово "Россия"
40 | **region** -- Название региона, откуда ваша газета
41 | **language** -- слово "ru"
42 |
43 | Таким образом, со страницы со статьей нужно еще извлечь, если возможно, имя автора, дату публикации, название публикации, приписанные категории.
44 |
45 | Кроме того, коллекция текстов с сайта газеты должна быть представлена в трёх видах (каждый вид в отдельной папке):
46 |
47 | 1. Неразмеченный текст в формате "для чтения" (текст разделен на абзацы тэгами
+ картинки, но ничего кроме этого).
48 |
49 | В нём перед текстом должны быть такие строки (после собаки и примыкающего к ней слова через пробел нужно написать релевантную информацию):
50 |
51 | @au имя автора (если автора нет, пишем Noname)
52 | @ti Название статьи
53 | @da дата в формате 12.02.2012
54 | @topic категория, если мы её можем найти на странице со статьёй
55 | @url URL, откуда мы скачали страницу
56 |
57 | 2. Размеченный mystem текст в формате XML
58 |
59 | 3. Размеченный mystem текст в формате plain text
60 |
61 |
62 | Соответственно, сама программа (в одном или в нескольких файлах) должна уметь:
63 |
64 | 1. Скачивать страницы с выбранного сайта, обходя его по принципу краулера. При этом программа не должна заходить на одни и те же страницы несколько раз.
65 | 2. Извлекать со страниц информацию для метатаблицы (если она доступна) и сам текст.
66 | 3. Генерировать вид "для чтения", убирая со страницы всю лишнюю информацию.
67 | 4. Раскладывать скачанные тексты по папкам.
68 | 5. Вызывать mystem и делать морфологическую разметку текста (таким образом, чтобы каждому слову была присвоена информация о лемме и грамматическая информация с учётом контекстно снятой омонимии).
69 |
70 |
71 | ## Про каталог еще раз
72 |
73 | Каталог должен выглядеть вот так:
74 |
75 | ```
76 | 📂газета
77 | |
78 | |____ metadata.csv
79 | |
80 | |____📂html
81 | | |
82 | | |____📂2016
83 | | | |
84 | | | |____📂1
85 | | | | |
86 | | | | |____ статья1.html
87 | | | | |
88 | | | | |____ статья2.html
89 | | | |
90 | | | |____📁2
91 | | |
92 | | |____📁2015
93 | |
94 | |____📂mystem-xml
95 | | |
96 | | |____📂2016
97 | | | |
98 | | | |____📂1
99 | | | | |
100 | | | | |____ статья1.xml
101 | | | | |
102 | | | | |____ статья2.xml
103 | | | |
104 | | | |____📁2
105 | | |
106 | | |____📁2015
107 | |
108 | |____📂mystem-plain
109 | |
110 | |____📂2016
111 | | |
112 | | |____📂1
113 | | | |
114 | | | |____ статья1.txt
115 | | | |
116 | | | |____ статья2.txt
117 | | |
118 | | |____📁2
119 | |
120 | |____📁2015
121 | ```
122 |
123 | ## Про устройство программы
124 |
125 | Подумаем, как может быть устроена ваша программа.
126 |
127 | **Путь первый**
128 |
129 | Для каждой задачи написать отдельную функцию. Написать главную функцию, которая запускает программу.
130 |
131 |
132 | **Путь второй**
133 |
134 | Можно для каждой логической группы функций создать отдельный файл, например, файл для функций, работающих с майстемом, файл для функций, выкачивающих газетные страницы и т.д. Создать главный файл, в котором прописана основная логика программы. В этот главный файл импортируются все остальные функции.
135 |
136 | ## Про папки
137 |
138 | Вспомним, как на питоне работать с папками. Для этого используется модуль `os`.
139 |
140 | Создать папку: `os.mkdir(dirname)` или `os.makedirs(dirname)`. `mkdir` создает директорию и вызывает ошибку, если она существует. `makedirs` создает директории и все несуществующие директории в указанном пути (например, если в `dirname` указан путь `./dir1/dir2/dir3`, и при этом dir1 и dir2 не существуют, то функция их создаст).
141 |
142 | Проверить, существует ли папка: `os.path.exists(dirname)` (возвращает `True` или `False`).
143 | Пройтись по каталогу: `os.walk(dirname)`.
144 |
145 | Вот такой маленький сниппет, возможно, вам пригодится:
146 | ```python
147 | import os
148 |
149 | if not os.path.exists(directory):
150 | os.makedirs(directory)
151 | ```
152 |
153 | ## Как просто вставить куски строки в шаблон
154 |
155 | Для такого форматирования можно использовать оператор %.
156 |
157 | `%s` в строке значит, что в это место вставится строка. `%d` значит, что в это место вставится число. Эти последовательности пишутся в том месте строки, куда нужно что-то вставить.
158 |
159 | После строки пишется знак `%` и затем кортеж (в круглых скобочках) из элементов, которые нужно вставить:
160 |
161 | ```python
162 | row = '%s\t%s\t\t\t%s\t%s\tпублицистика\t\t\t%s\t\tнейтральный\tн-возраст\tн-уровень\tрайонная(если районная)\t%s\tназвание газеты\t\t%s\tгазета\tРоссия\tкакой-то регион\tru'
163 |
164 | print(row % ('тут ссылка', 'Петя', 'Название статьи', '26.09.2016', 'образование', 'url', '2016'))
165 | print(row % ('тут другая ссылка', 'Автор', 'Другая статья', '27.09.2016', 'спорт', 'url2', '2016'))
166 | ```
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/Homeworks/Project.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Собери корпус из газет\n",
8 | "\n",
9 | "## Про проект\n",
10 | "Итак, уже скоро мы завершаем марафон \"Собери корпус из газет\". К концу сессионно недели, 29 октября (в 10:00), в репозитории должен лежать готовый код, который умеет делать всё, что перечислено ниже, а также в файле Readme.md в папке с проектом должна находиться ссылка на скачанные и обработанные файлы вашей газеты, лежащие **одним архивом** на Яндекс.Диске, Google Drive, Облаке@Мэйл.ру или на чём угодно подобном (но, пожалуйста, не надо заливать эти архивы на гитхаб).\n",
11 | "\n",
12 | "При этом \n",
13 | "\n",
14 | "1. Общий объём скачанных текстов должен быть не меньше 100 тыс. слов. \n",
15 | "2. В именах файлов не должно быть не-ascii символов (убираем их из url - [stackoverflow](https://stackoverflow.com/questions/4389572/how-to-fetch-a-non-ascii-url-with-python-urlopen)).\n",
16 | "3. Структура каталогов, в которых хранятся файлы, должна быть следующей: корень/год/месяц/файлы с материалами за этот месяц\n",
17 | "4. В корне также должна лежать csv-таблица с такими полями (разделитель - знак табуляции):"
18 | ]
19 | },
20 | {
21 | "cell_type": "code",
22 | "execution_count": null,
23 | "metadata": {},
24 | "outputs": [],
25 | "source": [
26 | "path\tauthor\theader\tcreated\tsphere\ttopic\tstyle\taudience_age\taudience_level\taudience_size\tsource\tpublication\tpubl_year\tmedium\tcountry\tregion\tlanguage"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "Имена полей означают следующее:\n",
34 | "\n",
35 | "**path** -- это путь к чистому неразмеченному файлу со статьёй, \n",
36 | "**author** -- имя автора, если его можно достать со страницы (и вообще если оно есть), \n",
37 | "**header** -- название статьи \n",
38 | "**created** -- дата в формате 07.01.2012 (день.месяц.год) \n",
39 | "**sphere** -- слово \"публицистика\" \n",
40 | "**topic** -- категория, если мы её можем найти на странице со статьёй \n",
41 | "**style** -- слово \"нейтральный\" \n",
42 | "**audience_age** -- слово \"н-возраст\" \n",
43 | "**audience_level** -- слово \"н-уровень\" \n",
44 | "**audience_size** -- \"районная\", если газета районная, \"республиканская\", если газета республиканская, \"городская\" -- если городская \n",
45 | "**source** -- URL, откуда статья была скачана \n",
46 | "**publication** -- название газеты \n",
47 | "**publ_year** -- год публикации \n",
48 | "**medium** -- слово \"газета\" \n",
49 | "**country** -- слово \"Россия\" \n",
50 | "**region** -- название региона, откуда ваша газета \n",
51 | "**language** -- слово \"ru\" \n",
52 | "\n",
53 | "Таким образом, со страницы со статьей нужно еще извлечь, если возможно, имя автора, дату публикации, название публикации, приписанные категории.\n",
54 | "\n",
55 | "Кроме того, коллекция текстов с сайта газеты должна быть представлена в трёх видах (каждый вид в отдельной папке):\n",
56 | "\n",
57 | "1. Неразмеченный текст. \n",
58 | "\n",
59 | " В нём перед текстом должны быть такие строки (после собаки и примыкающего к ней слова через пробел нужно написать релевантную информацию):\n",
60 | "\n",
61 | " @au имя автора (если автора нет, пишем None) \n",
62 | " @ti Название статьи \n",
63 | " @da дата в формате 12.02.2012 \n",
64 | " @topic категория, если мы её можем найти на странице со статьёй (если нет, пишем None) \n",
65 | " @url URL, откуда мы скачали страницу
\n",
66 | "\n",
67 | "2. Размеченный mystem текст в формате XML\n",
68 | "\n",
69 | "3. Размеченный mystem текст в формате plain text\n",
70 | "\n",
71 | "\n",
72 | "Соответственно, сама программа (в одном или в нескольких файлах) должна уметь:\n",
73 | "\n",
74 | "1. Скачивать страницы с выбранного сайта, обходя его по принципу краулера. При этом программа не должна заходить на одни и те же страницы несколько раз.\n",
75 | "2. Извлекать со страниц информацию для метатаблицы (если она доступна) и сам текст.\n",
76 | "3. Раскладывать скачанные тексты по папкам.\n",
77 | "4. Вызывать mystem и делать морфологическую разметку текста таким образом, чтобы каждому слову была присвоена информация о лемме и грамматическая информация с учётом контекстно снятой омонимии. Начальную форму печатать не нужно. Граммемы должны быть английскими. Каждое предложение должно быть с новой строки (т.е. нужно полностью копировать ввод на вывод). \n",
78 | "\n",
79 | "\n",
80 | "## Про каталог еще раз\n",
81 | "\n",
82 | "Каталог должен выглядеть вот так:"
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": null,
88 | "metadata": {
89 | "collapsed": true
90 | },
91 | "outputs": [],
92 | "source": [
93 | "📂газета\n",
94 | "|\n",
95 | "|____ metadata.csv\n",
96 | "|\n",
97 | "|____📂plain\n",
98 | "| |\n",
99 | "| |____📂2016\n",
100 | "| | |\n",
101 | "| | |____📂1\n",
102 | "| | | |\n",
103 | "| | | |____ статья1.txt\n",
104 | "| | | |\n",
105 | "| | | |____ статья2.txt\n",
106 | "| | |\n",
107 | "| | |____📁2\n",
108 | "| |\n",
109 | "| |____📁2015\n",
110 | "|\n",
111 | "|____📂mystem-xml\n",
112 | "| |\n",
113 | "| |____📂2016\n",
114 | "| | |\n",
115 | "| | |____📂1\n",
116 | "| | | |\n",
117 | "| | | |____ статья1.xml\n",
118 | "| | | |\n",
119 | "| | | |____ статья2.xml\n",
120 | "| | |\n",
121 | "| | |____📁2\n",
122 | "| |\n",
123 | "| |____📁2015\n",
124 | "|\n",
125 | "|____📂mystem-plain\n",
126 | " |\n",
127 | " |____📂2016\n",
128 | " | |\n",
129 | " | |____📂1\n",
130 | " | | |\n",
131 | " | | |____ статья1.txt\n",
132 | " | | |\n",
133 | " | | |____ статья2.txt\n",
134 | " | |\n",
135 | " | |____📁2\n",
136 | " |\n",
137 | " |____📁2015"
138 | ]
139 | },
140 | {
141 | "cell_type": "markdown",
142 | "metadata": {},
143 | "source": [
144 | "## Про устройство программы\n",
145 | "\n",
146 | "Подумаем, как может быть устроена ваша программа.\n",
147 | "\n",
148 | "**Путь первый** \n",
149 | "\n",
150 | "Для каждой задачи написать отдельную функцию. Написать главную функцию, которая запускает программу. При таком устройстве программы лучше писать ее в jupyter notebook.\n",
151 | "\n",
152 | "\n",
153 | "**Путь второй**\n",
154 | "\n",
155 | "Можно для каждой логической группы функций создать отдельный файл, например, файл для функций, работающих с майстемом, файл для функций, выкачивающих газетные страницы и т.д. Создать главный файл, в котором прописана основная логика программы. В этот главный файл импортируются все остальные функции. При таком устройстве программы каждый модуль будет отдельным скриптом с расширением .py"
156 | ]
157 | },
158 | {
159 | "cell_type": "markdown",
160 | "metadata": {},
161 | "source": [
162 | "## Про папки\n",
163 | "\n",
164 | "Вспомним, как на питоне работать с папками. Для этого используется модуль `os`.\n",
165 | "\n",
166 | "Создать папку: `os.mkdir(dirname)` или `os.makedirs(dirname)`. `mkdir` создает директорию и вызывает ошибку, если она существует. `makedirs` создает директории и все несуществующие директории в указанном пути (например, если в `dirname` указан путь `./dir1/dir2/dir3`, и при этом dir1 и dir2 не существуют, то функция их создаст).\n",
167 | " \n",
168 | "Проверить, существует ли папка: `os.path.exists(dirname)` (возвращает `True` или `False`).\n",
169 | "Пройтись по каталогу: `os.walk(dirname)`.\n",
170 | "\n",
171 | "Вот такой маленький сниппет, возможно, вам пригодится:"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "execution_count": null,
177 | "metadata": {
178 | "collapsed": true
179 | },
180 | "outputs": [],
181 | "source": [
182 | "import os\n",
183 | "\n",
184 | "if not os.path.exists(directory):\n",
185 | " os.makedirs(directory)"
186 | ]
187 | },
188 | {
189 | "cell_type": "markdown",
190 | "metadata": {},
191 | "source": [
192 | "## Как просто вставить куски строки в шаблон\n",
193 | "\n",
194 | "Для такого форматирования можно использовать оператор %. \n",
195 | "\n",
196 | "`%s` в строке значит, что в это место вставится строка. `%d` значит, что в это место вставится число. Эти последовательности пишутся в том месте строки, куда нужно что-то вставить. \n",
197 | "\n",
198 | "После строки пишется знак `%` и затем кортеж (в круглых скобочках) из элементов, которые нужно вставить:"
199 | ]
200 | },
201 | {
202 | "cell_type": "code",
203 | "execution_count": 8,
204 | "metadata": {},
205 | "outputs": [
206 | {
207 | "name": "stdout",
208 | "output_type": "stream",
209 | "text": [
210 | "тут ссылка\tПетя\tНазвание статьи\t26.09.2016\tпублицистика\t\tобразование\tнейтральный\tн-возраст\tн-уровень\tрайонная(если районная)\turl\tназвание газеты\t2016\tгазета\tРоссия\tкакой-то регион\tru\n"
211 | ]
212 | }
213 | ],
214 | "source": [
215 | "row = '%s\\t%s\\t%s\\t%s\\tпублицистика\\t\\t%s\\tнейтральный\\tн-возраст\\tн-уровень\\tрайонная(если районная)\\t%s\\tназвание газеты\\t%s\\tгазета\\tРоссия\\tкакой-то регион\\tru'\n",
216 | "\n",
217 | "print(row % ('тут ссылка', 'Петя', 'Название статьи', '26.09.2016', 'образование', 'url', '2016'))"
218 | ]
219 | },
220 | {
221 | "cell_type": "code",
222 | "execution_count": 9,
223 | "metadata": {},
224 | "outputs": [
225 | {
226 | "name": "stdout",
227 | "output_type": "stream",
228 | "text": [
229 | "тут другая ссылка\tАвтор\tДругая статья\t27.09.2016\tпублицистика\t\tспорт\tнейтральный\tн-возраст\tн-уровень\tрайонная(если районная)\turl2\tназвание газеты\t2016\tгазета\tРоссия\tкакой-то регион\tru\n"
230 | ]
231 | }
232 | ],
233 | "source": [
234 | "print(row % ('тут другая ссылка', 'Автор', 'Другая статья', '27.09.2016', 'спорт', 'url2', '2016'))"
235 | ]
236 | },
237 | {
238 | "cell_type": "markdown",
239 | "metadata": {},
240 | "source": [
241 | "Программа оценивается в 0 баллов в следующих случаях:\n",
242 | "- обнаружен плагиат;\n",
243 | "- скачано менее 100 000 слов.\n",
244 | "\n",
245 | "
\n",
246 | "
Балл
Критерий
\n",
247 | "
1
Программа запускается и оформлена по PEP8
\n",
248 | "
1
Программа разделена на функции
\t\n",
249 | "
2
Программа умеет автоматически скачивать материалы с выбранного сайта.
\n",
250 | "
1
Корректная структура папок, которая создается автоматически.
\n",
251 | "
1
Имена файлов содержат только ascii символы.
\n",
252 | "
2
Программа умеет автоматически извлекать метаданные со страницы и записывает их в CSV файл.
\n",
253 | "
2
Программа корректно использует MyStem для обработки текстов.
\n",
254 | "
2
Бонусный балл. Программа умеет генерировать вид \"для чтения\" (со страницы убираеются все ненужные данные кроме текста, разбитого на абзацы и картинок в этом тексте.
\n",
255 | "
\n"
256 | ]
257 | },
258 | {
259 | "cell_type": "code",
260 | "execution_count": null,
261 | "metadata": {},
262 | "outputs": [],
263 | "source": []
264 | }
265 | ],
266 | "metadata": {
267 | "kernelspec": {
268 | "display_name": "Python 3",
269 | "language": "python",
270 | "name": "python3"
271 | },
272 | "language_info": {
273 | "codemirror_mode": {
274 | "name": "ipython",
275 | "version": 3
276 | },
277 | "file_extension": ".py",
278 | "mimetype": "text/x-python",
279 | "name": "python",
280 | "nbconvert_exporter": "python",
281 | "pygments_lexer": "ipython3",
282 | "version": "3.6.6"
283 | }
284 | },
285 | "nbformat": 4,
286 | "nbformat_minor": 1
287 | }
288 |
--------------------------------------------------------------------------------
/Homeworks/QuestionnaireHW.md:
--------------------------------------------------------------------------------
1 | ## Проект №2 - Сайт-анкета
2 |
3 | Нужно написать сайт-анкету для (полевой) работы с информантом.
4 |
5 | **На сайте должны быть:**
6 |
7 | 1) Главная страница (127.0.0.1), на которой показывается анкета с полями.
8 | Данные, которые будут вводиться в анкету, должны записываться в файл (лучше всего csv).
9 |
10 | 2) Страница статистики (127.0.0.1/stats), на которой результаты должны систематизироваться и в удобном виде выводиться
11 | на экран (это могут быть таблицы, какие-то подсчеты и тд).
12 |
13 | 3) Страница с выводом всех данных (127.0.0.1/json), на которой возвращается json со всеми введенными на сайте данными. Этот json должен выводиться на веб-странице.
14 |
15 | 4) Страница поиска (127.0.0.1/search) и результатов поиска (127.0.0.1/results) .
16 | В ней нужно сделать минимум два поля поиска (например, текстовый ввод для поиска конкретного слова в ответах и чекбокс, где можно будет выбрать пол информанта). На странице должно быть описано, по каким данным ведется поиск.
17 |
18 | **Тема может быть любой**, вот примеры:
19 |
20 | - Лексико-типологическая анкета по какому-то лексическому полю (части тела, цвета, предметы мебели, домашняя утварь и всё, на что хватит вашей лингвистической фантазии). Анкета может быть в виде веб-формы с картинками того предмета/цвета, который должен назвать информант, и текстовыми полями, в которых он впишет названия предмета/цвета на своём языке. Кроме полей для названий предметов/цветов форма будет содержать поле, в котором информант должен будет указать свой язык.
21 | - Сбор словаря/грамматики в экспедиции. Например, в анкете могут быть слова из списка Сводеша, а информант должен ввести их перевод на свой язык. Кроме того, у каждого перевода может быть какой-то комментарий или какая-то другая дополнительная информация.
22 | - Сбор бытовой лексики русского языка. (Посмотрите, как это делает Борис Иомдин, например, вконтакте)
23 | - Что-то социолингвистическое, могут быть вопросы типа голосования (твОрог или творОг?) и обязательно информация о заполняющем (родной город, язык, возраст, образование, пол и тд)
24 | - Что-угодно другое лингвистическое и интересующее лично вас.
25 |
26 | ## Критерии
27 |
28 | |Балл|Критерий|
29 | |----|--------|
30 | |1|Программа запускается и оформлена по PEP8. Соответствие PEP8 можно проверить с помощью команды `pycodestyle my_script_name.py` в командной строке.|
31 | |2|На сайте есть главная страница с работающей формой-анкетой|
32 | |1|Данные из анкеты сохраняются в файл|
33 | |2|На сайте есть страница со статистикой по всем введенным данным|
34 | |2|На сайте есть страница, при обращении к которой программа выдает пользователю все результаты в json|
35 | |2|На сайте есть страница поиска; поиск работает|
36 | |**2**|**Дополнительный балл** за внешнее оформление сайта с использованием [bootstrap](https://www.w3schools.com/booTsTrap/default.asp)|
37 | |**1**|**Дополнительный балл:** на странице со статистикой есть визуализация: график или диаграмма, сделанная с помощью `matplotlib`|
38 |
39 | **NB!** Это задание лучше выполнять не в тетрадке, а в виде скрипта с расширением `.py`. Папка с html-файлами должна называться `templates` и лежать рядом с файлом программы. Если у вас есть картинки, то там же должна быть папка `static` с ними.
40 |
41 | ### Как вставить картинку в сайт на фласке?
42 |
43 | Картинки нужно сложить в папку `static`. В html-шаблоне нужно написать:
44 |
45 | ``
46 |
47 | Чтобы просто вставить картинку в html (без фласка), нужно написать так:
48 | ``
49 |
--------------------------------------------------------------------------------
/Lessons/Flask/10. Flask (2) .ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Flask (2)\n",
8 | "\n",
9 | "## Словари в шаблонах\n",
10 | "\n",
11 | "Предположим, у нас есть словарь, в котором хранятся имена наших друзей и их почтовые адреса. И мы хотим выводить эти имена с адресами на нашем сайте. Мы можем написать что-то такое:"
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": 4,
17 | "metadata": {
18 | "collapsed": true
19 | },
20 | "outputs": [],
21 | "source": [
22 | "from flask import Flask\n",
23 | "from flask import render_template\n",
24 | "\n",
25 | "app = Flask(__name__)\n",
26 | "\n",
27 | "\n",
28 | "@app.route('/')\n",
29 | "def index():\n",
30 | " emailbook = {'Петя': 'petya@example.com',\n",
31 | " 'Вася': 'vasya@example.com',\n",
32 | " 'Катя': 'katya@example.com'}\n",
33 | " return render_template('index.html', emails=emailbook)\n",
34 | "\n",
35 | "if __name__ == '__main__':\n",
36 | " app.run()"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "Тогда в папке `templates` нам нужно создать файл `index.html`, в котором будут перебираться элементы словаря. Делается это с помощью функции `items()`. Вот так будет выглядеть `index.html`:"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": null,
49 | "metadata": {
50 | "collapsed": true
51 | },
52 | "outputs": [],
53 | "source": [
54 | "\n",
55 | "\n",
56 | "\n",
57 | " \n",
58 | " Почтовые адреса\n",
59 | "\n",
60 | "\n",
61 | "
Адреса моих друзей
\n",
62 | "
\n",
63 | " {% for name, email in emails.items() %}\n",
64 | "
{{ name }} - {{ email }}
\n",
65 | " {% endfor %}\n",
66 | "
\n",
67 | "\n",
68 | ""
69 | ]
70 | },
71 | {
72 | "cell_type": "markdown",
73 | "metadata": {},
74 | "source": [
75 | "## Перенаправление\n",
76 | "\n",
77 | "Для того, чтобы направить пользователя на другую страницу, используется функция `redirect`. Например, вот приложение, в котором есть страница /time. С помощью функции `redirect` можно, например, реализовать такое:\n",
78 | "\n",
79 | "- если пользователь заходит на страницу /time в рабочее время (с 10 до 18), то он перенаправляется на главную страницу сайта,\n",
80 | "- если пользователь заходит на страницу в другое время, то он перенаправляется на страницу /hi."
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": null,
86 | "metadata": {
87 | "collapsed": true
88 | },
89 | "outputs": [],
90 | "source": [
91 | "import datetime\n",
92 | "\n",
93 | "from flask import Flask\n",
94 | "from flask import url_for, render_template, request, redirect\n",
95 | "\n",
96 | "app = Flask(__name__)\n",
97 | "\n",
98 | "\n",
99 | "@app.route('/')\n",
100 | "def index():\n",
101 | " return '
Привет, мир!
'\n",
102 | "\n",
103 | "\n",
104 | "@app.route('/hi')\n",
105 | "@app.route('/hi/')\n",
106 | "def hi(user=None):\n",
107 | " if user is None:\n",
108 | " user = 'friend'\n",
109 | " return '
Привет, ' + user + '!
'\n",
110 | "\n",
111 | "\n",
112 | "@app.route('/time')\n",
113 | "def time_redirect():\n",
114 | " h = datetime.datetime.today().hour\n",
115 | " if 10 < h < 18:\n",
116 | " return redirect(url_for('index'))\n",
117 | " return redirect(url_for('hi'))\n",
118 | "\n",
119 | "\n",
120 | "if __name__ == '__main__':\n",
121 | " app.run(debug=True)"
122 | ]
123 | },
124 | {
125 | "cell_type": "markdown",
126 | "metadata": {},
127 | "source": [
128 | "Когда вы пишете сайт на фласке у себя на компьютере, можно написать вместо `app.run()` вот так: `app.run(debug=True)` (см. выше последнюю строчку). Это значит, что если на сайте возникнет ошибка, то на странице с ошибкой выведется ее описание, и вы легко сможете понять, в каком месте кода все падает. Но когда вы будете выкладывать сайт в Интернет, нужно убедиться, что `debug` отключен.\n",
129 | "\n",
130 | "## Как вывести на веб-страничку содержимое текстового файла?"
131 | ]
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": 10,
136 | "metadata": {},
137 | "outputs": [],
138 | "source": [
139 | "from flask import Flask\n",
140 | "from flask import url_for, render_template, request, redirect\n",
141 | "\n",
142 | "app = Flask(__name__)\n",
143 | "\n",
144 | "@app.route('/poem')\n",
145 | "def poem():\n",
146 | " with open(\"poem.txt\", \"r\", encoding='utf-8') as f:\n",
147 | " content = f.read().split('\\n')\n",
148 | " return render_template(\"poem.html\", content=content)\n",
149 | "\n",
150 | "if __name__ == '__main__':\n",
151 | " app.run(debug=True)"
152 | ]
153 | },
154 | {
155 | "cell_type": "code",
156 | "execution_count": 8,
157 | "metadata": {},
158 | "outputs": [],
159 | "source": [
160 | "\n",
161 | "\n",
162 | "\n",
163 | " \n",
164 | " Зимнее утро\n",
165 | "\n",
166 | "\n",
167 | "
\n",
173 | "\n",
174 | ""
175 | ]
176 | },
177 | {
178 | "cell_type": "markdown",
179 | "metadata": {},
180 | "source": [
181 | "## Задание для тренировки\n",
182 | "\n",
183 | "Скачайте из репозитория [список языковых кодов](https://github.com/elmiram/2016learnpython/blob/master/data/lang_codes.csv). \n",
184 | "После этого нужно создать сайт, в котором:\n",
185 | "1. На главной странице выводится список языков и их кодов (`127.0.0.1:5000`),\n",
186 | "2. Если зайти на страницу вида `127.0.0.1:5000/codes/какие-то_буквы`, то на этой странице выведется список только тех языков, коды которых начинаются с этих букв. Например, если зайти на `127.0.0.1:5000/codes/jp`, то выведется японский и еврейско-персидский, а если зайти на `127.0.0.1:5000/codes/j`, то японский, еврейско-персидский, еврейско-арабский и яванский.\n",
187 | "3. Есть форма на странице `127.0.0.1:5000/form`, в которой есть поле \"Язык\". В это поле пользователь будет вводить название языка, например \"японский\". Когда пользователь нажимает кнопку \"Отправить\", \n",
188 | " * если введенного языка нет в списке, пользователь попадает на страницу `127.0.0.1:5000/not_found` с соответствующим сообщением,\n",
189 | " * если введенный язык есть в списке, пользователь должен попасть на страницу `127.0.0.1:5000/lang/код_языка`. На этой странице должно выводиться следующее: название введенного языка, код введенного языка, названия всех языков, код которых начинается на ту же букву.\n",
190 | "4. На всех страницах есть кликабельная ссылка на главную и на страницу с формой.\n",
191 | "\n",
192 | "Пример сайта на фласке есть в репозитории [вот тут](https://github.com/ancatmara/learnpython2017/tree/master/%D0%A1%D0%B5%D0%BC%D0%B8%D0%BD%D0%B0%D1%80%D1%8B/flask_example). Там есть примеры использования всех функций фласка, которые мы проходили. (*Туда можно подглядывать.*)"
193 | ]
194 | }
195 | ],
196 | "metadata": {
197 | "kernelspec": {
198 | "display_name": "Python 3",
199 | "language": "python",
200 | "name": "python3"
201 | },
202 | "language_info": {
203 | "codemirror_mode": {
204 | "name": "ipython",
205 | "version": 3
206 | },
207 | "file_extension": ".py",
208 | "mimetype": "text/x-python",
209 | "name": "python",
210 | "nbconvert_exporter": "python",
211 | "pygments_lexer": "ipython3",
212 | "version": "3.6.6"
213 | }
214 | },
215 | "nbformat": 4,
216 | "nbformat_minor": 1
217 | }
218 |
--------------------------------------------------------------------------------
/Lessons/Flask/9. Flask (1).ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {
6 | "collapsed": true
7 | },
8 | "source": [
9 | "# Пишем сайты на питоне\n",
10 | "\n",
11 | "## Вспоминаем, как работает интернет\n",
12 | "\n",
13 | "__Веб-сервер__\n",
14 | "* устройство vs. программа\n",
15 | "* задача — получать запросы от других компьютеров или программ (клиентов, clients) и отправлять запрошенные данные\n",
16 | "* основная функция — размещение сайтов (website hosting)\n",
17 | "\n",
18 | "__Термины__\n",
19 | "* *Запрос (request)* — сообщение от агента, желающего получить или разместить информацию\n",
20 | "* *Ответ (response)* — ответное сообщение сервера с кодом состояния и информацией (HTML, изображения, загружаемые файлы и т. п.)\n",
21 | "* *Протокол (protocol)* — набор правил, по которым составляются запросы и ответы \n",
22 | "* *Сессия (session)* — установка соединения между агентом и сервером и последующая серия запросов и ответов\n",
23 | "* *Гипертекст* — множество текстов, организованных в виде графа при помощи гиперссылок\n",
24 | "* *Протокол HTTP (HyperText Transfer Protocol)* — протокол для передачи гипертекстовых данных (обычно в виде HTML)\n",
25 | "* *URL (Uniform Resource Locator)*, веб-адрес ресурса — строка, представляющая собой уникальное имя, по которому можно найти в сети этот ресурс\n",
26 | "\n",
27 | "__Адресация__\n",
28 | "\n",
29 | "IP\n",
30 | "* *IP-адрес* — (пока что) набор из 4 байт, присваиваемый каждому подключённому к сети устройству\n",
31 | "* Некоторые IP-адреса уникальны, некоторые — нет (внутренние адреса в локальных сетях)\n",
32 | "* Практически любой ресурс (например, сайт) можно получить по его IP-адресу (например, через браузер)\n",
33 | "* Существуют зарезервированные адреса и диапазоны адресов, например, `127.0.0.1` — адрес данного устройства\n",
34 | "\n",
35 | "Порт\n",
36 | "* Каждый запрос обращается не просто к какому-то IP-адресу, а к некоторому порту на этом адресе\n",
37 | "* Веб-сервер имеет 65 535 портов, пронумерованных начиная с 1\n",
38 | "* Веб-сервер может прослушивать некоторые порты (listen to ports) и по-разному обрабатывать сообщения, поступившие на разные порты\n",
39 | "* Если порт не прослушивается, сообщения на этот порт останутся без ответа\n",
40 | "\n",
41 | "\n",
42 | "__URL__\n",
43 | "\n",
44 | "`http__://__www.example.com__:__1234__/__directory1/file1.html`\n",
45 | "\n",
46 | "`протокол__://__доменное имя или IP-адрес__:__порт__/__адрес файла на сервере`\n",
47 | "\n",
48 | "* Порт указывать не обязательно: используются стандартные порты (HTTP — 80, FTP — 20 и т. п.)\n",
49 | "* *DNS (Domain Name Servers)* — специальные сервера в сети, на которых хранятся таблицы соответствия между доменными именами и IP-адресами их серверов\n",
50 | "\n",
51 | "\n",
52 | "__HTML и скрипты__\n",
53 | "* страницы, содержимое (HTML-код) которых не изменяется, называются *статическими (static)*\n",
54 | "* страницы, содержимое которых может быть разным в зависимости от введённых пользователем данных, времени, IP-адреса и т. п., называются *динамическими (dynamic)*\n",
55 | "* динамические страницы создаются с помощью скриптов *на стороне сервера (server side scripts)*, написанных, например, на PHP или Python\n",
56 | "* скрипт порождает HTML и посылает его пользователю\n",
57 | "* пользователь не видит кода скрипта, выполняющегося на сервере\n",
58 | "* *скрипт на стороне клиента (client side script)* — вставка в HTML на каком-то языке программирования (например, JavaScript), позволяющая странице вести себя интерактивно\n",
59 | "* код клиентских скриптов посылается клиенту сервером вместе с HTML и не выполняется на сервере\n",
60 | "\n",
61 | "__Питон и сайты__\n",
62 | "\n",
63 | "Написать сайт на питоне значит написать такую программу, которая может работать веб-сервером или использоваться веб-сервером для порождения HTML-кода веб-страниц. Для этого существует несколько модулей, например, Django и Flask\n",
64 | "\n",
65 | "## flask\n",
66 | "\n",
67 | "### Intro\n",
68 | "\n",
69 | "* Программа, написанная с помощью flask, работает как веб-сервер\n",
70 | "* За каждую веб-страницу сайта отвечает какая-то функция, которая возвращает HTML- код этой страницы\n",
71 | "* Естественно, писать длинные куски HTML-кода внутри программы на питоне было бы странно, поэтому функции могут загружать HTML из заранее заготовленных файлов\n",
72 | "* Эти файлы могу содержать готовые страницы или шаблоны страниц на специальном языке\n",
73 | "\n",
74 | "Пример готового сайта на flask:"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {},
81 | "outputs": [
82 | {
83 | "name": "stderr",
84 | "output_type": "stream",
85 | "text": [
86 | " * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)\n",
87 | "127.0.0.1 - - [29/May/2018 16:23:17] \"GET / HTTP/1.1\" 200 -\n",
88 | "127.0.0.1 - - [29/May/2018 16:23:17] \"GET /favicon.ico HTTP/1.1\" 404 -\n",
89 | "127.0.0.1 - - [29/May/2018 16:23:17] \"GET /favicon.ico HTTP/1.1\" 404 -\n",
90 | "127.0.0.1 - - [29/May/2018 16:23:17] \"GET / HTTP/1.1\" 200 -\n"
91 | ]
92 | }
93 | ],
94 | "source": [
95 | "from flask import Flask\n",
96 | "\n",
97 | "app = Flask(__name__)\n",
98 | "\n",
99 | "@app.route('/')\n",
100 | "def index():\n",
101 | " return '
Hello, world!
'\n",
102 | "\n",
103 | "if __name__ == '__main__':\n",
104 | " app.run(debug=False)"
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "Каждая страница сайта порождается какой-то функцией. Декоратор `@app.route(...)` перед функцией показывает, какой адрес будет у страницы, за которую отвечает эта функция:"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": null,
117 | "metadata": {
118 | "collapsed": true
119 | },
120 | "outputs": [],
121 | "source": [
122 | "@app.route('/')\n",
123 | "def index():\n",
124 | " return 'Main page'\n",
125 | "\n",
126 | "@app.route('/hi')\n",
127 | "def hi():\n",
128 | " return 'Hi!'"
129 | ]
130 | },
131 | {
132 | "cell_type": "markdown",
133 | "metadata": {},
134 | "source": [
135 | "Одна функция может отвечать за несколько разных страниц:\n",
136 | "* Во-первых, декораторов может стоять несколько подряд.\n",
137 | "* Во-вторых, декораторы могут содержать переменные.\n",
138 | "\n",
139 | "Пример:"
140 | ]
141 | },
142 | {
143 | "cell_type": "code",
144 | "execution_count": null,
145 | "metadata": {
146 | "collapsed": true
147 | },
148 | "outputs": [],
149 | "source": [
150 | "@app.route('/user/')\n",
151 | "def user_index(user):\n",
152 | " return 'This is the page of' + user"
153 | ]
154 | },
155 | {
156 | "cell_type": "markdown",
157 | "metadata": {},
158 | "source": [
159 | "Переменные в адресах могут быть разного типа: `int` — целое число, `float` — действительное число, `path` — строка, которая может содержать слэши. Тип переменной можно указать вот так:"
160 | ]
161 | },
162 | {
163 | "cell_type": "code",
164 | "execution_count": null,
165 | "metadata": {
166 | "collapsed": true
167 | },
168 | "outputs": [],
169 | "source": [
170 | "import datetime\n",
171 | "\n",
172 | "@app.route('/time/')\n",
173 | "def time_page(shift):\n",
174 | " h = datetime.datetime.today().hour\n",
175 | " h += shift\n",
176 | " return 'Time in your country:' + str(h)"
177 | ]
178 | },
179 | {
180 | "cell_type": "markdown",
181 | "metadata": {},
182 | "source": [
183 | "Страницы часто содержат ссылки друг на друга, но чтобы поставить ссылку, нужно знать адрес. Чтобы узнать адрес страницы, которую создаёт какая-то функция, используется функция `url_for`:"
184 | ]
185 | },
186 | {
187 | "cell_type": "code",
188 | "execution_count": null,
189 | "metadata": {
190 | "collapsed": true
191 | },
192 | "outputs": [],
193 | "source": [
194 | "from flask import url_for\n",
195 | "\n",
196 | "@app.route('/functions/')\n",
197 | "def f_address(fname):\n",
198 | " return 'The address is ' + url_for(fname)"
199 | ]
200 | },
201 | {
202 | "cell_type": "markdown",
203 | "metadata": {},
204 | "source": [
205 | "### Обратная связь\n",
206 | "(вспоминаем прошлый семинар)\n",
207 | "\n",
208 | "* Для обратной связи с сервером часто используются HTML-формы\n",
209 | "* Форма должна содержать кнопку `Submit`\n",
210 | "* Формы могут содержать текстовые поля, галочки и т. п.\n",
211 | "* Данные (значения элементов) из формы отправляются на сервер с помощью метода GET или POST\n",
212 | "* При использовании метода GET данные приписываются к URL после знака `?`\n",
213 | "\n",
214 | "__Еще раз про HTML-формы__"
215 | ]
216 | },
217 | {
218 | "cell_type": "code",
219 | "execution_count": null,
220 | "metadata": {
221 | "collapsed": true
222 | },
223 | "outputs": [],
224 | "source": [
225 | ""
232 | ]
233 | },
234 | {
235 | "cell_type": "markdown",
236 | "metadata": {},
237 | "source": [
238 | "При нажатии на кнопку `submit` и использовании GET на сервер отправляется запрос, URL которого содержит все значения параметров после `?`:\n",
239 | "\n",
240 | " www.example.com:5000/some_page.html?name=Petya&age=&student=on\n",
241 | "\n",
242 | "Почти все символы в таком URL, кроме латинских, будут закодированы с помощью percent encoding:\n",
243 | "\n",
244 | " name=%D0%A2%D0%B8%D0%BC%D0%BE%D1%84%D0%B5%D0%B9\n",
245 | "\n",
246 | "Чтобы использовать данные из формы в приложении flask, нужен объект `request`:\n",
247 | "* `request.method` — метод запроса\n",
248 | "* `request.args` — словарь со значениями аргументов из URL"
249 | ]
250 | },
251 | {
252 | "cell_type": "code",
253 | "execution_count": null,
254 | "metadata": {
255 | "collapsed": true
256 | },
257 | "outputs": [],
258 | "source": [
259 | "from flask import request\n",
260 | "@app.route('/login')\n",
261 | "def login():\n",
262 | " if request.args['password'] == '123':\n",
263 | " return 'Name: ' + request.args['login']"
264 | ]
265 | },
266 | {
267 | "cell_type": "markdown",
268 | "metadata": {},
269 | "source": [
270 | "\n",
271 | "### Шаблоны\n",
272 | "\n",
273 | "Динамические веб-страницы собираются из шаблонов: у шаблона есть постоянная часть и изменяющаяся часть. Flask позволяет хранить в файлах такие шаблоны страниц. __(!!!) Все шаблоны страниц должны находиться в папке `templates`.__\n",
274 | "\n",
275 | "Шаблон состоит из обычного html-кода. Но в этот обычный html могут быть вставлены специальные фрагменты кода, способного порождать разный html в зависимости от значений переменных. \n",
276 | "\n",
277 | "Эти специальные фрагменты пишутся внутри `{% ... %}` или `{{ ... }}`. При порождении HTML эти фрагменты заменяются на какой-то HTML-код по определённым правилам.\n",
278 | "\n",
279 | "Чтобы породить HTML по шаблону, используется функция `render_template()`:"
280 | ]
281 | },
282 | {
283 | "cell_type": "code",
284 | "execution_count": null,
285 | "metadata": {
286 | "collapsed": true
287 | },
288 | "outputs": [],
289 | "source": [
290 | "from flask import render_template\n",
291 | "@app.route('/hello/')\n",
292 | "@app.route('/hello/')\n",
293 | "def hello(name=None):\n",
294 | " return render_template('hello.html', name=name)"
295 | ]
296 | },
297 | {
298 | "cell_type": "markdown",
299 | "metadata": {},
300 | "source": [
301 | "* Функция `render_template` заменяет все вставки в фигурных скобках на какой-то HTML.\n",
302 | "* Во вставках можно использовать переменные, которые передаются в шаблон через `render_template`.\n",
303 | "\n",
304 | "Есть два вида вставок: `{{ ... }}` и `{% ... %}`.\n",
305 | "\n",
306 | "Язык, на котором пишутся эти вставки, похож на питон, но многие питоновские функции в шаблонах работать не будут\n",
307 | "\n",
308 | "__Вставки `{{ ... }}`__\n",
309 | "\n",
310 | "* `{{ ... }}` означает «вычислить значение выражения в скобках и заменить им вставку»\n",
311 | "* в скобках может быть переменная, например, `{{ name }}`\n",
312 | "* к переменным в скобках __нельзя__ применять произвольные функции: `{{ f(name) }}`\n",
313 | "* существует набор встроенных операций, которые можно выполнять над переменными\n",
314 | "* эти операции отделяются от переменной знаком | и тогда выражение пишется так `{{ name|length }}`, примеры операций: \n",
315 | " * `length`\n",
316 | " * `lower`, `upper`\n",
317 | " * `e` — автоматически экранировать спецсимволы HTML\n",
318 | " * `random` — взять случайный элемент из массива\n",
319 | " * `urlencode` — закодировать строку с помощью percent encoding\n",
320 | "\n",
321 | "__Вставки `{% ... %}`__\n",
322 | "\n",
323 | "В таких `{% ... %}` скобках пишутся специальные команды, аналогичные питоновским `if` и `for`.\n",
324 | "Примеры:\n",
325 | "\n",
326 | "`{% for i in arr %} ... {% endfor %}`\n",
327 | "\n",
328 | "`{% if ... %} ... {% endif %}`\n",
329 | "\n",
330 | "`{% elif ... %}`\n",
331 | "\n",
332 | "`{% else %}`\n"
333 | ]
334 | },
335 | {
336 | "cell_type": "code",
337 | "execution_count": null,
338 | "metadata": {
339 | "collapsed": true
340 | },
341 | "outputs": [],
342 | "source": [
343 | "{% if username|length > 20 %}\n",
344 | "
Слишком длинное имя!
\n",
345 | "{% else %}\n",
346 | "
{{ username }}
\n",
347 | "{% endif %}"
348 | ]
349 | },
350 | {
351 | "cell_type": "markdown",
352 | "metadata": {},
353 | "source": [
354 | "### Задание\n",
355 | "\n",
356 | "Написать приложение на фласке, которое позволяет узнать длину введенного пользователем слова в символах.\n",
357 | "\n",
358 | "1. На главной странице, index.html, пользователь должен ввести свое имя в форму. Форме должен предшествовать какой-нибудь текст, например *\"На этом сайте можно узнать длину любого слова. Представьтесь, пожалуйста, чтобы продолжить\"*.\n",
359 | "2. После отправки формы должен происходить редирект на страницу с текстом вроде *\"Здравствуйте, %user%! Введите какое-нибудь слово, а я посчитаю его длину\".* Т.е. в этом тексте обязательно должно быть употреблено имя пользователя, введенное в предыдущей форме. После этого текста должна быть еще одна форма, куда можно ввести слово. Страницу можно назвать как угодно -- главное, осмысленно.\n",
360 | "3. После отправки формы из пункта №2 результаты должны появляться на той же странице, текст примерно такой: *\"Вы ввели слово %word%. Его длина в символах -- %length%\".*"
361 | ]
362 | }
363 | ],
364 | "metadata": {
365 | "kernelspec": {
366 | "display_name": "Python 3",
367 | "language": "python",
368 | "name": "python3"
369 | },
370 | "language_info": {
371 | "codemirror_mode": {
372 | "name": "ipython",
373 | "version": 3
374 | },
375 | "file_extension": ".py",
376 | "mimetype": "text/x-python",
377 | "name": "python",
378 | "nbconvert_exporter": "python",
379 | "pygments_lexer": "ipython3",
380 | "version": "3.6.6"
381 | }
382 | },
383 | "nbformat": 4,
384 | "nbformat_minor": 1
385 | }
386 |
--------------------------------------------------------------------------------
/Lessons/Flask/flask_example/my_app.py:
--------------------------------------------------------------------------------
1 | import datetime
2 |
3 | from flask import Flask
4 | from flask import url_for, render_template, request, redirect
5 |
6 | app = Flask(__name__)
7 |
8 |
9 | @app.route('/')
10 | def index():
11 | urls = {'главная (эта страница)': url_for('index'),
12 | 'привет (переменные в url)': url_for('hi'),
13 | 'форма (форма и ответ на одном url)': url_for('form'),
14 | 'форма про книги (просто форма)': url_for('books'),
15 | 'спасибо (попадаем сюда только после формы про книги)': url_for('thanks'),
16 | 'время (используем redirect)': url_for('time_redirect'),}
17 | return render_template('index.html', urls=urls)
18 |
19 |
20 | @app.route('/hi')
21 | @app.route('/hi/')
22 | def hi(user=None):
23 | if user is None:
24 | user = 'друг'
25 | return '
Мы записали, что это ваша любимая книга: {{ book }}.
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Lessons/Flask/langcodes.csv:
--------------------------------------------------------------------------------
1 | Абазинский,abq
2 | Абхазский,abk
3 | Авадхи,awa
4 | Аварский,ava
5 | Авестийский,ave
6 | Адангме,ada
7 | Адыгейский,ady
8 | Азербайджанский,aze
9 | Аймара,aym
10 | Айну,ain
11 | Акан,aka
12 | Аккадский,akk
13 | Албанский,sqi
14 | Алеутский,ale
15 | Алтайский,alt
16 | Амхарский,amh
17 | Английский,eng
18 | Арабский,ara
19 | Аравакский,arw
20 | Арамейский,arc
21 | Арапахо,arp
22 | Арауканский,arn
23 | Армянский,hye/axm/xcl
24 | Ассамский,asm
25 | Ассирийский,aii
26 | Атапачские,ath
27 | Афарский,aar
28 | Африкаанс,afr
29 | Африхили,afh
30 | Ахвахский,akv
31 | Ацтекский,nah
32 | Ачехский,ace
33 | Ачоли,ach
34 | Балийский,ban
35 | Бамбара,bam
36 | Банда,bad
37 | Баса,bas
38 | Баскский,eus
39 | Башкирский,bak
40 | Беджа,bej
41 | Белорусский,bel
42 | Белуджский,bal
43 | Бемба,bem
44 | Бенгальский,ben
45 | Бикольский,bik
46 | Бини,bin
47 | Бирманский,mya
48 | Бислама,bis
49 | Болгарский,bul
50 | Боснийский,bos
51 | Брауи,brh
52 | Бретонский,bre
53 | Бугийский,bug
54 | Бурятский,bua
55 | Бходжпури,bho
56 | Ваи,vai
57 | Валлийский,cym
58 | Варай,war
59 | Вашо,was
60 | Венгерский,hun
61 | Венда,ven
62 | Вепсский,vep
63 | Воламо,wal
64 | Волапюк,vol
65 | Волоф,wol
66 | Вьетнамский,vie
67 | Га,gaa
68 | Гавайский,haw
69 | Гагаузский,gag
70 | Гайо,gay
71 | Галисийский,glg
72 | Ганда,lug
73 | Гереро,her
74 | Геэз,gez
75 | Гилбертский,gil
76 | Гонди,gon
77 | Готский,got
78 | Гребо,grb
79 | Гренландский,kal
80 | Греческий (новогреческий),ell
81 | Грузинский,kat
82 | Гуарани,grn
83 | Гуджарати,guj
84 | Гэльский,gla
85 | Дакота,dak
86 | Даргинский,dar
87 | Датский,dan
88 | Делавэрский,del
89 | Дзонг-кэ,dzo
90 | Дивехи (Мальдивский),div
91 | Динка,din
92 | Диула (Дьюла),dyu
93 | Догри,doi
94 | Древнегреческий,grc
95 | Древнеегипетский,egy
96 | Древнерусский,orv
97 | Древнесаксонский,osx
98 | Дуала,dua
99 | Дунганский,dng
100 | Еврейско-арабский,jrb
101 | Еврейско-персидский,jpr
102 | Зенагский,zen
103 | Зулу,zul
104 | Зуньи,zun
105 | Ибанский,iba
106 | Иврит,heb
107 | Игбо,ibo
108 | Идиш,yid
109 | Илоко,ilo
110 | Ингушский,inh
111 | Индонезийский,ind
112 | Интерлингва,ina
113 | Интерлингве,ile
114 | Инуктитут,iku
115 | Инупиак,ipk
116 | Ирландский,gle
117 | Исландский,isl
118 | Испанский,spa
119 | Итальянский,ita
120 | Ительменский,itl
121 | Йоруба,yor
122 | Кабардино-черкесский,kbd
123 | Кабильский,kab
124 | Кави,kaw
125 | Каддо,cad
126 | Казахский,kaz
127 | Калмыцкий,xal
128 | Камба,kam
129 | Каннада,kan
130 | Канури,kau
131 | Караимский,kdr
132 | Каракалпакский,kaa
133 | Карачаево-балкарский,krc
134 | Карельский,krl
135 | Кариб,car
136 | Каталанский,cat
137 | Качинский,kac
138 | Кашмири,kas
139 | Кечуа,que
140 | Кикуйю,kik
141 | Киньяма,kua
142 | Киргизский,kir
143 | Китайский,zho
144 | Коми,kom
145 | Коми-пермяцкий,koi
146 | Конго,kon
147 | Конкани,kok
148 | Коптский,cop
149 | Корейский,kor
150 | Корнский,cor
151 | Корсиканский,cos
152 | Корякский,kpy
153 | Коса,xho
154 | Кпелле,kpe
155 | Крик,mus
156 | Крымско-татарский,crh
157 | Кумыкский,kum
158 | Курдский,kur
159 | Курух,kru
160 | Кусайе,kos
161 | Кутенай,kut
162 | Кхаси,kha
163 | Кхмерский,khm
164 | Ладино,lad
165 | Лакский,lbe
166 | Ламба,lam
167 | Лаосский,lao
168 | Латинский,lat
169 | Латышский,lav
170 | Лахнда,lah
171 | Лезгинский,lez
172 | Лингала,lin
173 | Литовский,lit
174 | Лози,loz
175 | Луба-катанга,lub
176 | Луисеньо,lui
177 | Лунда,lun
178 | Луо (Кения и Танзания),luo
179 | Люксембургский,ltz
180 | Магахи,mag
181 | Мадурский,mad
182 | Майтхили,mai
183 | Макассарский,mak
184 | Македонский,mkd
185 | Малагасийский,mlg
186 | Малайский,msa
187 | Малаялам,mal
188 | Мальтийский,mlt
189 | Мандинго,man
190 | Манипури,mni
191 | Мансийский (Вогульский),mns
192 | Маори,mri
193 | Маратхи,mar
194 | Марвари,mwr
195 | Марийский (черемисский),chm
196 | Маршалльский,mah
197 | Масаи,mas
198 | Менде,men
199 | Микмак,mic
200 | Минангкабау,min
201 | Мокшанский,mdf
202 | Молдавский,mol
203 | Монго,lol
204 | Монгольский,mon
205 | Мооре,mos
206 | Мохаук,moh
207 | Мэнский (Мэнкский),glv
208 | Навахо,nav
209 | Нанайский (гольдский),gld
210 | Науру,nau
211 | Ндебеле северный,nde
212 | Ндебеле южный,nbl
213 | Ндунга,ndo
214 | Неварский,new
215 | Неидентифицированный,und
216 | Немецкий,deu
217 | Ненецкий (юрако-самоедский),yrk
218 | Непальский,nep
219 | Нзима,nzi
220 | Нивхский (гиляцкий),niv
221 | Нидерландский (Голландский),nld
222 | Нидерландский средневековый,dum
223 | Ниуэ,niu
224 | Ногайский,nog
225 | Норвежский [Norsk (bokm?l)]?,nor
226 | Ньоро,nyo
227 | Ньямвези,nym
228 | Ньянджа,nya
229 | Ньянколе,nyn
230 | Нюнорск (новонорвежский) [Norsk (nynorsk)]?,nno
231 | Оджибве,oji
232 | Окситанский,oci
233 | Ория,ori
234 | Оромо,orm
235 | Оседжи,osa
236 | Осетинский,oss
237 | Палау,pau
238 | Пали,pli
239 | Пампанга,pam
240 | Пангасинан,pag
241 | Папьяменто,pap
242 | Пенджабский,pan
243 | Персидский,fas
244 | Пехлевийский,pal
245 | Польский,pol
246 | Понапе,pon
247 | Португальский,por
248 | Пушту,pus
249 | Раджастхани,raj
250 | Разных семей языки,mul
251 | Раротонга,rar
252 | Ретороманский,roh
253 | Руанда,kin
254 | Румынский,ron
255 | Рунди,run
256 | Русский,rus
257 | Саамский,smi
258 | Самаритянский арамейский,sam
259 | Самоанский,smo
260 | Санго,sag
261 | Сандаве,sad
262 | Санскрит,san
263 | Сапотекский,zap
264 | Сардинский,srd
265 | Свази,ssw
266 | Себуано,ceb
267 | Селькупский,sel
268 | Сербский,srp
269 | Серер,srr
270 | Сибирскотатарский,sty
271 | Сидама,sid
272 | Сиксика,bla
273 | Сингальский,sin
274 | Синдхи,snd
275 | Сирийский,syr
276 | Словацкий,slk
277 | Словенский,slv
278 | Согдийский,sog
279 | Сомали,som
280 | Сото северный,nso
281 | Сото южный,sot
282 | Среднеанглийский,enm
283 | Средневерхненемецкий,gmh
284 | Среднеирландский,mga
285 | Среднефранцузский,frm
286 | Староанглийский,ang
287 | Староверхненемецкий,goh
288 | Староирландский,sga
289 | Старонорвежский,non
290 | Староперсидский,peo
291 | Старопровансальский,pro
292 | Старотурецкий,ota
293 | Старофранцузский,fro
294 | Суахили,swa
295 | Сукума,suk
296 | Сунданский,sun
297 | Сусу,sus
298 | Табасаранский,tab
299 | Тагальский,tgl
300 | Таджикский,tgk
301 | Таитянский,tah
302 | Тайский,tha
303 | Талышский,tly
304 | Тамашек,tmh
305 | Тамильский,tam
306 | Татарский,tat
307 | Тви,twi
308 | Телугу,tel
309 | Темне,tem
310 | Терено,ter
311 | Тибетский,bod
312 | Тиви,tiw
313 | Тигре,tig
314 | Тигринья,tir
315 | Тлингит,tli
316 | Тонга (Ньяса),tog
317 | Тонганский,ton
318 | Трукский,chk
319 | Тсвана,tsn
320 | Тсонга,tso
321 | Тувинский,tyv
322 | Тумбука,tum
323 | Турецкий,tur
324 | Туркменский,tuk
325 | Угаритский,uga
326 | Удмуртский (вотяцкий),udm
327 | Удэгейский,ude
328 | Узбекский,uzb
329 | Уйгурский,uig
330 | Украинский,ukr
331 | Ульчский,ulc
332 | Умбунду,umb
333 | Урду,urd
334 | Фанг,fan
335 | Фанти,fat
336 | Фарерский,fao
337 | Фиджи,fij
338 | Филиппинский,fil
339 | Финикийский,phn
340 | Финский (Suomi),fin
341 | Фон,fon
342 | Французский,fra
343 | Фризский,fry
344 | Фулах,ful
345 | Хайда,hai
346 | Хакасский,kjh
347 | Хантыйский (остяцкий),kca
348 | Хауса,hau
349 | Хилигайнон,hil
350 | Хинди,hin
351 | Хиримоту,hmo
352 | Хорватский,hrv
353 | Хотанский,kho
354 | Хупа,hup
355 | Цахурский,tkr
356 | Церковнославянский (Старославянский),chu
357 | Цимшиан,tsi
358 | Цыганский,rom
359 | Чагатайский,chg
360 | Чаморро,cha
361 | Чероки,chr
362 | Чеченский,che
363 | Чешский,ces
364 | Чжуанский,zha
365 | Чибча,chb
366 | Чинук жаргон,chn
367 | Чоктав,cho
368 | Чувашский,chv
369 | Чукотский,ckt
370 | Шайенн (Чейенн),chy
371 | Шанский,shn
372 | Шведский,swe
373 | Шона,sna
374 | Шорский,cjs
375 | Шотландский (англо-шотландский),sco
376 | Шугнанский,sgh
377 | Шумерский,sux
378 | Эве,ewe
379 | Эвенкийский (тунгусский),evn
380 | Эвенский,eve
381 | Эвондо,ewo
382 | Экаджук,eka
383 | Эламский,elx
384 | Эрзянский,myv
385 | Эсперанто,epo
386 | Эстонский,est
387 | Эфик,efi
388 | Яванский,jav
389 | Якутский (Саха),sah
390 | Яо,yao
391 | Яп,yap
392 | Японский,jpn
393 |
--------------------------------------------------------------------------------
/Lessons/Heroku и командная строка/13a. Heroku.md:
--------------------------------------------------------------------------------
1 | # Heroku
2 |
3 | ## PaaS
4 |
5 | Мы с вами научились выкладывать наши сайты и ботов на Pythonanywhere, но это не единственный вариант. Существуют другие подобные сервисы - [Heroku](https://www.heroku.com/), [Scalingo](https://scalingo.com/), [Openshift](https://www.openshift.com/).
6 |
7 | Все они являются PaaS - Platform-as-a-Service, которые позволяют вам очень просто пользоваться облачным хостингом и быстро выкладывать свои приложения вместо того, чтобы самостоятельно настраивать сервер.
8 |
9 | От Pythonanywhere они отличаются тем, что для них разработчиками не всегда предоставлен такой же удобный веб-интерфейс, в котором многое делается кнопочками в панели управления, и нужный функционал мы получем через командную строку Unix. Но ощее с Pythonanywhere у них то, что там есть возможность делать хотя бы что-то из того, что вам нужно, бесплатно.
10 |
11 | Дело в том, что вслед за компанией Amazon многие другие IT-компании стали предоставлять пользователям (в числе которых и частные лица, и компании поменьше) облачные сервисы, то есть возможность не содержать на свои средства большой парк серверов (это часто неудобно, потому что бесперебойную работу серверов обеспечить не так просто), а покупать место на мощных серверах, которые содержит хозяин облака. Основные конкурирующие на этом поле сервисы -- это [Amazon Web Services](https://aws.amazon.com/ru/), [Google Cloud](https://cloud.google.com/) и [Microsoft Azure](https://azure.microsoft.com/ru-ru/). Все они платные (Google предоставляет на своей платформе условно-бесплатный тестовый период в один месяц), но мощные и надёжные.
12 |
13 | ## Почему еще и Heroku?
14 |
15 | У бесплатных аккаунтов Heroku есть некоторое количество преимуществ перед аналогичными аккаунтами Pythonanywhere:
16 |
17 | |Pythonanywhere | Heroku |
18 | | --- | --- |
19 | |только одно приложение | несколько приложений |
20 | | свой домен - платная функция | позволяет использовать собственное доменое имя |
21 | | ограниченный доступ к внешним ресурсам | доступ к внешним ресурсам не ограничен |
22 |
23 | __Подробнее про ограниченный доступ__: на Pythonanywhere можно обращаться лишь к тем сайтам, которые входят в белый список разрешенных ресурсов. Т.е. например, наш сайт, который регулярно скачивает новости с hse.ru не будет работать на Pythonanywhere, потому что hse.ru не включен в белый список. На Heroku таких ограничений нет.
24 |
25 | __Подробнее про количество бесплатных приложений__: на Heroku можно создавать несколько приложений бесплатно лишь до тех пор, пока у вас есть свободные Dyno (про это будет ниже).
26 |
27 |
28 | ## Подготовка к выкладыванию
29 |
30 | 1) Чтобы наш фласк-сайт или фласк-бот заработал на Heroku, нужно убедиться, что в конце основной программы написан вот такой код:
31 |
32 | ```python
33 | if __name__ == '__main__':
34 | import os
35 | app.debug = True
36 | port = int(os.environ.get("PORT", 5000))
37 | app.run(host='0.0.0.0', port=port)
38 | ```
39 |
40 |
41 | 2) В директории с вашим фласк-приложением обязательно должны быть следующие три файла:
42 | * __`requirements.txt`__ - в этом файле нужно перечислить все не стандартные питоновские модули, которые необходимы для вашей программы. В списке нужно указать не только название модуля, но и нужную вам версию. Выглядеть это будет примерно так:
43 |
44 |
45 | Flask==0.12.1
46 | pymorphy2==0.8
47 | pymystem3==0.1.5
48 | requests==2.13.0
49 |
50 |
51 | Обратите внимание, что в этот список НЕ НУЖНО писать setuptools и pip!
52 |
53 | Когда вы будете выкладывать приложение, Heroku прочитает файл `requirements.txt` и установит все перечисленные модули командой `pip install -r requirements.txt`.
54 |
55 | * __`runtime.txt`__ - в этом файле нужно написать одну строчку:
56 |
57 | python-3.6.1
58 |
59 | Если в директории нет `runtime.txt`, то Heroku будет по умолчанию думать, что ваше приложение написано на Python 2.7.
60 |
61 | * __`Procfile`__ - обратите внимание, что у файла нет расширения, иначе heroku не сможет прочитать его содержимое. В этом файле нужно написать одну строчку:
62 |
63 | web: python flask_app.py
64 |
65 | Вместо `flask_app.py` нужно написать название вашего файла с фласк-приложением. `Procfile` - это специальный файл, в котором нужно объяснить Heroku, как именно нужно запускать ваше приложение. `web` значит, что мы написали приложение, которое отвечает на http-запросы, `python flask_app.py` обозначает команду, с помощью которой приложение запускается.
66 |
67 |
68 | 3) Для выкладывания приложений на Heroku используется git. Поэтому если в вашей директории с проектом еще нет git-репозитория, его нужно создать. Открываем терминал (Mac, Linux) или командную строку (Windows) и пишем:
69 | * `cd путь-к-директории` - переходим в директорию с нашим фласк-проектом,
70 | * `git init` - создаем в текущей директории репозиторий,
71 | * `git add *` - говорим гиту следить за всеми файлами в репозитории,
72 | * `git commit -m 'Initial commit'` - делаем первый коммит.
73 |
74 |
75 | ## Как выложить сайт на Heroku?
76 |
77 | 1) Зарегистрироваться на сайте [Heroku](https://www.heroku.com/), ваш email будет логином. Когда вы зарегистрировались, вы попадаете в Dashboard. Сейчас у вас там ничего нет - вам предлагают создать приложение (an app) или пройти туториал по работе с Heroku и выбранного вами языка программирования. Туториал по питону там ориентирован на джанго, мы работаем с фласком, так что наши действия будут слегка отличаться.
78 |
79 | 2) Скачать установщик для вашей ОС и установить Heroku CLI - Command Line Interface - https://devcenter.heroku.com/articles/heroku-cli
80 |
81 | 3) Открыть терминал (Mac, Linux) или командную строку (Windows) и выполнить команды:
82 |
83 | * __`cd путь-к-директории`__ - переходим в директорию с нашим фласк-проектом,
84 | * __`heroku login`__ - логинимся в наш аккаунт Heroku,
85 | * ввести свой емейл и пароль, с которыми мы зарегистрировались,
86 | * __`heroku create`__ - создаем приложение, которое поможет Heroku получить наш код и запустить его. В этот момент Heroku делает сразу несколько вещей.
87 |
88 | Во-первых, он генерирует случайное название для нашего приложения, но можно передать ваше собственное название, например, `heroku create my-app-04062017`. Ваш сайт будет доступен по адресу `имя-приложения.herokuapp.com`.
89 |
90 | Во-вторых, к вашему репозиторию добавляется удаленный репозиторий (git remote), который называется `heroku`. У одного локального репозитория на вашем компьютере может быть несколько удаленных (например, у вас может быть `origin` - это ваш удаленный репозиторий на GitHub, и `heroku` - удаленный репозиторий на Heroku.)
91 |
92 | * __`git push heroku master`__ - эта команда отправляет наш код на облачный хостринг, и Heroku устанавливает нужные модули.
93 | * __`heroku ps:scale web=1`__ - эта команда говорит запустить наш фласк-сайт на одном dyno.
94 |
95 | > A dyno is a lightweight Linux container that runs a single user-specified command.
96 |
97 | То есть ваш сайт или бот будет работать на маленьком виртуальном Линукс-"сервере". Бесплатно вам доступно 550 или 1000 таких dyno.
98 |
99 | * __`heroku open`__ - эта команда открывает ваш сайт в браузере. Ура! Все готово!
100 | * Если по какой-то причине сайт не заработал, то нужно посмотреть логи:
101 |
102 | - __`heroku logs`__ - эта команда распечатает 100 последних строчек логов, т.е. если произошла какая-то ошибка, то информацию об этой ошибке вы увидите в конце логов.
103 | - или __`heroku logs --tail`__ - эта команда показывает логи в реальном времени, т.е. если ваша программа что-то печатает в консоль с помощью `print(...)` или питон печатает сообщение об ошибке, то вы будете в реальном времени видеть, что именно происходит.
104 | - подробнее - https://devcenter.heroku.com/articles/logging
105 |
106 | Когда вы меняете что-то в вашей программе\директории, то изменения нужно отправить на Heroku:
107 |
108 | git add *
109 | git commit -m "Demo"
110 | git push heroku master
111 | heroku ps:scale web=1
112 |
113 |
114 | ## Секретные ключи
115 |
116 | Поскольку мы отправляем все файлы на Heroku через git, возникает небольшая проблема:
117 |
118 | Что если у нас есть секретные файлы (например, API-токены или пароли), которые включены в `.gitignore`? Получается, мы никак не сможем отправить эти секретные файлы на облачный хостинг через git.
119 |
120 | ### Переменные среды
121 | Для работы с секретами рекомендуется использовать [переменные среды](https://en.wikipedia.org/wiki/Environment_variable): ваши ключи будут храниться в текстовых переменных вашей системы и в вашем Heroku-приложении, но при этом они никогда не попадут в открытый git-репозиторий.
122 |
123 | Раньше мы с вами писали секретные ключи в игнорируемый файл (например, `TOKEN = "......"` внутри `conf.py`) и импортировали секретные переменные с помощью `from conf import *`.
124 |
125 | Вместо этого, можно установить переменную среды прямо в терминале\командной строке:
126 |
127 | * Mac, Linux - `export SOME_SECRET_KEY=1c3-cr3am-15-yummy`
128 | * Windows - `set SOME_SECRET_KEY 1c3-cr3am-15-yummy` **(если у вас Windows 10, то `setx`)**
129 | * Heroku - `heroku config:set SOME_SECRET_KEY=1c3-cr3am-15-yummy`
130 |
131 | После этого и на вашем компьютере, и в облачном хостинге Heroku переменную среды можно прочитать с помощью питона:
132 |
133 | ```python
134 | >>> import os
135 | >>> os.environ["SOME_SECRET_KEY"]
136 | "1c3-cr3am-15-yummy"
137 | ```
138 |
139 |
140 | То есть строчку `from conf import *` вам придется заменить на строчки вида:
141 |
142 | ```python
143 | import os
144 | SOME_SECRET_KEY = os.environ["SOME_SECRET_KEY"]
145 | ```
146 |
147 |
148 | Кроме того, старые вебхуки с адресом на pythonanywhere уже не действительны, и их надо заменить на адрес вашего приложения. В целом, код очень простого бота из первого конспекта по телеграму, адаптированный под Heroku, будет выглядеть вот так:
149 |
150 | ```python
151 | import flask
152 | import telebot
153 | import os
154 |
155 | TOKEN = os.environ["TOKEN"]
156 |
157 |
158 | bot = telebot.TeleBot(TOKEN, threaded=False)
159 |
160 |
161 | bot.remove_webhook()
162 | bot.set_webhook(url="https://.herokuapp.com/bot")
163 |
164 | app = flask.Flask(__name__)
165 |
166 | @bot.message_handler(commands=['start', 'help'])
167 | def send_welcome(message):
168 | bot.send_message(message.chat.id, "Здравствуйте! Это бот, который считает длину вашего сообщения.")
169 |
170 |
171 | @bot.message_handler(func=lambda m: True) # этот обработчик реагирует все прочие сообщения
172 | def send_len(message):
173 | bot.send_message(message.chat.id, 'В вашем сообщении {} символов.'.format(len(message.text)))
174 |
175 | @app.route("/", methods=['GET', 'HEAD'])
176 | def index():
177 | return 'ok'
178 |
179 | # страница для нашего бота
180 | @app.route("/bot", methods=['POST'])
181 | def webhook():
182 | if flask.request.headers.get('content-type') == 'application/json':
183 | json_string = flask.request.get_data().decode('utf-8')
184 | update = telebot.types.Update.de_json(json_string)
185 | bot.process_new_updates([update])
186 | return ''
187 | else:
188 | flask.abort(403)
189 |
190 | if __name__ == '__main__':
191 | import os
192 | app.debug = True
193 | port = int(os.environ.get("PORT", 5000))
194 | app.run(host='0.0.0.0', port=port)
195 | ```
196 |
197 |
198 | ## Как запустить что-то по расписанию?
199 |
200 | Если вы делаете какой-то веб-сервис, который должен обновлять какие-то данные через определённые промежутки времени (например, каждый день в 12:00 или каждый четверг в 17:25), то вы можете настроить стандартную Unix-утилиту cron, которая умеет запускать на сервере какой-то нужный пользователю процесс в тот момент, когда это ему необходимо.
201 |
202 | Утилита cron обычно уже входит в стандартную сборку дистрибутива и устанавливать её не нужно. Она имеет текстовый интерфейс настройки, то есть расписание придётся писать через консоль, в одном из консольных текстовых редакторов. Наиболее популярный из них -- [Vim](https://ru.wikipedia.org/wiki/Vim). Он не очень прост в обращении, потому что неинтуитивен. Перед тем, как его запускать, узнайте, [как его закрыть](https://ru.wikibooks.org/wiki/Vim) (почти как в сказке, нужно помнить про "горшочек, не вари", прежде чем сказать "горшочек, вари"). Недавно крупный сайт подсказок и ответов на вопросы о программировании Stackoverflow опубликовал [новость](https://stackoverflow.blog/2017/05/23/stack-overflow-helping-one-million-developers-exit-vim/), из которой следует, что вопрос "как выйти из Vim" является чуть ли не самым популярным при поиске вопросом.
203 |
204 | Есть и другой консольный редактор, nano, он проще и все команды, которые вы должны выполнить для тех или иных действий, постоянно показываются внизу экрана ("крышечка" означает "Ctrl"):
205 |
206 | 
207 |
208 | Однако он не установлен по умолчанию во всех дистрибутивах, и, возможно, его придётся установить самостоятельно.
209 |
210 | Создать или отредактировать расписание можно вызовом команды `crontab -e`. В открывшемся окне нужно будет описать [в формате cron](http://www.nncron.ru/nncronlt/help/RU/working/cron-format.htm), что вы хотите, чтобы было сделано, и когда это должно быть сделано. Формат cron подразумевает, что вы напишете `минута час день_месяца месяц день_недели команда`, а потом -- то, что должно будет запуститься, в том виде, в котором бы вы сами это запускали вручную в командной строке.
211 |
212 | Примеры расписания в cron:
213 |
214 | ```
215 | # нечто будет выполняться каждую минуту:
216 | * * * * * python3 /home/user/script.py
217 |
218 | # только по выходным:
219 | * * * * 6,7 python3 /home/user/weekend.py
220 |
221 | # дважды в день:
222 | 20 11,16 * * * python3 /home/user/twice.py
223 |
224 | # один раз в году, в полночь 1-го января:
225 | 0 0 1 1 * python3 /home/user/HappyNewYear.py
226 |
227 | ```
228 |
229 | Обратите внимание, что к программам нужно писать полный путь, потому что cron ничего не знает про то, какую директорию вы считаете рабочей.
230 |
231 | ## Полезная ссылка
232 |
233 | [Тут](https://tproger.ru/translations/telegram-bot-create-and-deploy/amp/) можно найти ещё одно руководство по запуску бота на хероку.
234 |
235 |
236 |
237 |
--------------------------------------------------------------------------------
/Lessons/Heroku и командная строка/13b. Командная строка UNIX, логин на сервере.md:
--------------------------------------------------------------------------------
1 | # Командная строка UNIX, удалённый логин на сервере
2 | ## О чём речь?
3 |
4 | Помимо пользовательских компьютеров, которые мы используем в своей жизни для личных нужд и для работы (они называются "десктопами"), важное место в компьютерной инфраструктуре занимают так называемые "серверы". Это тоже компьютеры, обычно чуть более мощные и надёжные, чем десктопы, они могут располагаться в специальных [ЦОДах или дата-центрах](https://ru.wikipedia.org/wiki/%D0%94%D0%B0%D1%82%D0%B0-%D1%86%D0%B5%D0%BD%D1%82%D1%80) а ещё часто они постоянно подключены к Сети 24/7 и именно они обеспечивают работоспособность сайтов в Интернете и многих других сервисов, может быть, напрямую не связанных именно с Интернетом, например, банковских переводов.
5 |
6 | Когда мы через какой-нибудь браузер *заходим на сайт*, на самом деле за этим процессом стоит соединение по сети нашего компьютера с таким вот сервером (он называется "удалённым", потому что физически удалён от нас, может быть, на тысячи километров), который обрабатывает наш запрос, а одновременно с ним в ту же секунду может так же отвечать ещё тысячам других пользователей.
7 |
8 | Поэтому, чтобы, например, сделать свой собственный сайт, нужно иметь под рукой такой *сервер*, то есть компьютер, который будет, как минимум, постоянно подключён к Интернету, а ещё будет мощным и надёжным.
9 |
10 | ## UNIX и интерфейсы
11 |
12 | Из-за требований к надёжности и по ряду других исторических и коммерческих причин большинство серверов управляется не привычными для десктопа операционными системами семейства Windows или Mac OS, а операционными системами, которые называют UNIX-подобными, то есть воспроизводящими некоторые концептуальные идеи придуманной когда-то давно ОС UNIX (на самом деле, Mac OS X тоже является UNIX-подобной, и многое из того, о чём мы говорим ниже, справедливо и для неё). Прежде всего, это операционные системы (т.н. "дистрибутивы") на основе ядра Linux, а также в последнее время теряющие в популярности ОС семейства BSD. На практике (помимо других важных отличий) это обычно означает, что пользователю во всех этих системах предоставляется более-менее сходный интерфейс управления. И этот интерфейс не графический, то есть в нём нет привычных нам кнопочек и окон. То есть в принципе кнопочки и окошки (GUI -- graphic user interface) для UNIX-подобных систем возможны, но на серверах они не используются.
13 |
14 | Таким образом, те, кто взаимодействует с серверами: выкладывает на них свои сайты или занимается их обслуживанием ("администрирует"), пользуются интерфейсом командной строки, command line interface. Все вы немного имели с ним дело, когда изучали git и Mystem. Но для git есть и графические клиенты. С серверами и Mystem альтернативы командной строке почти нет.
15 |
16 | ## Командная строка
17 |
18 | Командная строка позволяет делать всё то, что пользователь привык делать, щёлкая мышкой: переходить между директориями, создавать и удалять файлы и папки, запускать программы. На самом деле, возможности командной строки даже шире и многообразнее, чем в графическом интерфейсе.
19 |
20 | Все эти возможности предоставляются таким образом. В текстовое поле вводится какая-то команда, представляющая собой зарезервированное слово, а для исполнения нажимается клавиша "Enter". Каждое такое слово -- это имя какой-нибудь маленькой программы, которая таким образом исполняется и делает то, что нам нужно. Например, она в каждый момент времени пользователь находится в каком-то конкретном месте файловой системы (дерева каталогов), и чтобы переместиться по ней вверх или вниз, нужно исполнить программу `cd` ("change directory"), передав ей параметр -- целевой каталог, куда нужно перейти. Например, ввод `cd text` приведёт к переходу пользователя во вложенную в текущую директорию "text" (если та и правда существует).
21 |
22 | ## Пробуем!
23 |
24 | Чтобы попробовать, как это работает, нужно загрузить реальную UNIX-подобную операционную систему. Мы будем тренироваться на дистрибутиве на основе ядра Linux, который называется Ubuntu, он действительно установлен в качестве основной операционки на многих серверах по всему миру. Запускать отдельный компьютер при этом не обязательно, операционную систему можно запустить внутри так называемой "виртуальной машины", то есть программы, которая делает вид, что она настоящий компьютер, а операционная система управляет этой программой и при этом думает, что управляет настоящим компьютером.
25 |
26 | 
27 |
28 |
29 |
30 | *Кадр из фильма Man In Black: видна галактика, которая думает, что она находится в настоящей вселенной*
31 |
32 | В этом классе установлен менеджер виртуальных машин VirtualBox. Нужно запустить его и включить там виртуальную машину с Ubuntu.
33 |
34 | Если у вас всё получилось, то нужно щёлкнуть по логотипу Ubuntu в левом верхнем углу и в строке поиска напечатать Terminal (или нажать одновременно `Ctrl + Alt + T`). Здесь можно вводить команды для работы с интерфейсом командной строки. Команд этих существует великое множество, но начать нужно с простого.
35 |
36 | Прежде всего, нужно осмотреться. Слева от курсора написано, какую директорию командная строка считает текущей. Если там содержится символ \~, то это указание на так называемую "домашнюю директорию", то есть "порт приписки" того пользователя, под именем которого вы залогинились в системе. Там же вы увидите символ доллара, который можете помнить по документации к Mystem.
37 |
38 | Для UNIX-систем очень важно, под каким именем вы логинитесь в системе, и одна из центральных идей этой операционной системы резко отличается от того, что можно наблюдать в Windows. В Windows обычно кто угодно может сделать всё, что угодно. В UNIX за каждым пользователем чётко закреплены его права: что он может делать и чего не может. Скажем, пользователь обычно может создавать, изменять и удалять файлы и папки в своей домашней директории, которая располагается по адресу `/home/`, но не может никак изменять или удалять файлы в директориях, созданных другими пользователями. Это помогает сделать систему более безопасной, и надёжной, потому что в такой ситуации гораздо труднее случайно испортить что-нибудь важное. Поэтому не пытайтесь что-то изменять за пределами своей папки `/home/`, всё равно ничего не получится (в принципе, возможности для этого есть, но только при наличии специальных привилегий).
39 |
40 | Попробуем какие-нибудь команды. Выведем на экран список вложенных файлов и каталогов (если там ничего нет, то на экране ничего и не появится):
41 |
42 | ```
43 | ls
44 | ```
45 |
46 | (ls -- от "list")
47 |
48 |
49 | Теперь перейдём на уровень вверх и снова посмотрим на все лежащие тут файлы и папки:
50 |
51 | ```
52 | cd ../
53 | ls
54 | ```
55 |
56 | Распечатаем полный путь к текущей директории:
57 |
58 | ```
59 | pwd
60 | ```
61 |
62 | Теперь вернёмся в домашнюю директорию, ведь только там мы можем делать что-нибудь законно (то есть не имея каких-то специальных прав):
63 |
64 | ```
65 | cd
66 | ```
67 |
68 | Теперь попробуем сделать то, что обычно делаем через графический интерфейс на своих десктопных компьютерах:
69 |
70 | Создадим директорию с именем "dir1":
71 |
72 | ```
73 | mkdir dir1
74 | ```
75 |
76 | Перейдём в неё:
77 |
78 | ```
79 | cd dir1
80 | ```
81 | Теперь создадим файл `test.txt` и что-нибудь туда запишем.
82 |
83 | ```
84 | echo "This is my first file" > test.txt
85 | ```
86 | В примере выше символ > отправляет аутпут команды слева в файл, указанный справа. Если такого файла нет, система автоматически его создаст. Но есть и специальная команда для создания файлов, `touch`.
87 |
88 | ```
89 | touch test-1.txt
90 | ls
91 | ```
92 |
93 | Команда `echo`выводит на экран последующую строку или значение переменной. Например, мы можем посмотреть значение системной переменной PATH.
94 |
95 | ```
96 | echo $PATH
97 | ```
98 | Теперь поищем что-нибудь в файле `test.txt` командой `grep` -- например, сочетание букв "is".
99 | У этой команды очень много возможностей, и подробнее про нее можно почитать [вот здесь](http://aidalinux.ru/w/Grep).
100 |
101 | ```
102 | grep is < test.txt
103 | ```
104 | Можно искать не только внутри файла, но и в названиях файлов и папок. Для этого в качестве аргумента нужно передать команде `grep ` список файлов -- например, это может быть аутпут команды `ls`. Символ | (pipe) передает аутпут одной команды другой команде в качестве инпута.
105 |
106 | ```
107 | ls | grep test
108 | ```
109 |
110 | И еще один пример с | -- сортировка (в обратном порядке, чтобы было интереснее).
111 |
112 | ```
113 | ls | sort -r
114 | ```
115 |
116 | Теперь скачаем сюда какой-нибудь файл из Интернета (без urllib.request!) и убедимся в том, что он действительно появился и выведем его содержимое на экран:
117 |
118 | ```
119 | wget http://web-corpora.net/Test1/hello.py
120 | ls
121 | cat
122 | ```
123 |
124 | Это файл на питоне. Попробуем его запустить из командной строки:
125 |
126 | ```
127 | python hello.py
128 | ```
129 |
130 | Получилось!
131 |
132 | Теперь копируем этот файл на уровень выше, а исходный удалим.
133 |
134 | ```
135 | cp hello.py ../
136 | rm hello.py
137 | ```
138 | Файл `test.txt` переместим на уровень выше командой `mv` (по сути это то же самое , что мы сделали выше, только в одно действие), а файл `test-1.txt` просто удалим.
139 |
140 | ```
141 | mv text.txt ../
142 | rm test-1.txt
143 | ```
144 |
145 | Теперь удалим директорию "dir1" (мы сможем это сделать только если она будет пустой):
146 |
147 | ```
148 | cd ../
149 | rmdir dir1
150 | ```
151 |
152 | Что ещё можно сделать из командной строки? [Очень-очень много всего!](http://forum.ubuntu.ru/index.php?topic=14535.15)
153 |
154 | Потренироваться можно даже не имея под рукой виртуальной машины под VirtualBox. На [этом сайте](http://bellard.org/jslinux/) вы найдёте Linux-систему без графической оболочки прямо в своём браузере. Там работает большинство команд, которые используются в интерфейсе командной строки UNIX-подобных систем.
155 |
156 | Если на сервере установлен git, то можно склонировать на него репозиторий с гитхаба.
157 |
158 | ## Удалённый доступ, SSH
159 |
160 | Поскольку UNIX-подобные системы чаще всего установлены на удалённых серверах, а не на компьютерах, которые есть у нас под рукой, нужно уметь соединяться (логиниться) с такими компьютерами удалённо. Для этого нужно знать логин и пароль доступа к удалённому серверу, его адрес (например, IP-адрес) и иметь программу, которая знает специальный протокол, по которому обычно происходит такое соединение. Этот протокол (не единственный, но самый распространённый) называется SSH (secure shell). На юникс-подобных системах такие программы уже установлены по умолчанию, а вот на Windows их нужно специально устанавливать. Самый распространённый инструмент такого рода -- программа PuTTY, она есть на компьютерах в этом классе.
161 |
162 | 
163 |
164 | В поле Host Name нужно ввести IP-адрес сервера, поставить галочку на "SSH" и нажать "Open". Дальше сервер запросит у вас логин и пароль (их, как и IP-адрес сервера вам сообщит преподаватель, писать их в открытом виде на гитхабе небезопасно). Обратите внимание, что когда вы будете печатать пароль, на экране ничего не будет происходить. Ни звёздочек, ни точек появляться не будет. Так и нужно. Пароль всё равно печатается. Введите его и нажмите "Enter". Если всё пройдёт успешно, вы окажетесь в домашней директории пользователя.
165 |
166 |
167 |
--------------------------------------------------------------------------------
/Lessons/Heroku и командная строка/cmd cheatsheet.md:
--------------------------------------------------------------------------------
1 | **Командная строка** - это такое окошко, куда можно вписать команду, и компьютер ее выполнит. На Windows она называется cmd, на Linux - Terminal. В командной строке вы увидите свое текущее местоположение (например, `ancatmara@INGEN C:\Users\ancatmara`), а на следующей строке - особый символ, который означает, что можно вводить команду. На Windows это **>**, а на Linux - **$**.
2 |
3 | Стандартный терминал cmd на Windows очень неудобный, так что можно выбрать и установить альтернативный вариант, [прочитав вот эту статью](https://habrahabr.ru/post/164687/).
4 |
5 | ## Самые главные команды в командной строке Windows и Linux
6 |
7 | | Значение | Windows | Linux / MacOS |
8 | | ------------- |-------------:| -----:|
9 | | Переход в другую директорию | cd | cd |
10 | | Создание файла | copy con | touch|
11 | | Создание папки | mkdir | mkdir |
12 | | Удаление файла | del, erase | rm; rm -rf -- удалить папку и все файлы в ней |
13 | | Удаление папки | rmdir | rmdir |
14 | | Вывод на экран сообщения | echo | echo |
15 | | Вывод на экран содержимого файла | type | cat|
16 | | Копирование файлов | copy, xcopy | cp |
17 | | Переименование файлов | ren, rename | mv |
18 | | Перемещение файлов | move | mv |
19 | | Поиск файлов | where | find, locate |
20 | | Вывод списка файлов и каталогов| dir | ls, dir |
21 | | Помощь | help | apropos, man, whatis |
22 |
23 |
24 | **Циркумфлекс** (вот этот знак "^") означает нажатие клавиши с Ctrl (^C = Ctrl + C).
25 |
26 | ^C — Прерывает команду, ну это все знают.
27 |
28 | ^S — Приостанавливает выполнение команды, а потом запускает.
29 |
30 | ^I — Аналог Tab, перебирает папки и файлы.
31 |
32 | ^M — Аналог Enter.
33 |
34 | ^H — Аналог Backspace.
35 |
36 | ## Работа с Python
37 |
38 | |Команда| Значение|
39 | |-------| -------:|
40 | |python| Запустить питон в терминале |
41 | |python --version| Посмотреть версию питона|
42 | |pip freeze| Посмотреть список установленных пакетов|
43 | |pip install| Установить пакет|
44 | |pip uninstall| Удалить пакет|
45 | |pip show| Показать информацию о конкретном пакете|
46 | |pip search| Найти пакет (если вы хотите установить что-то новое, но точно не помните название)|
47 |
48 | Подробнее про работу с pip можно почитать [на официальном сайте с документацией](https://pip.pypa.io/en/stable/).
49 |
50 | Если у вас установлена Анаконда, то вы можете пользоваться аналогом pip, который называется conda. Для него есть свой собсвенный [cheatsheet](https://conda.io/docs/_downloads/conda-cheatsheet.pdf) и [сайт с документацией](https://conda.io/docs/index.html).
51 |
52 | **NB!** Если команды python и pip не работают, вернитесь к семинару №8 и почитайте про настройку окружения.
53 |
54 | ## Работа с Git
55 |
56 | У git очень много возможностей, и про работу с ним написаны толстые книжки. Здесь перечислены только самые часто употребляемые команды.
57 |
58 | |Команда| Значение|
59 | |-------| -------:|
60 | |git clone| Склонировать репозиторий по указанной ссылке|
61 | |git pull| Скачать изменения из удаленного репозитория|
62 | |git init| Создать репозиторий |
63 | |git status| Посмотреть статус изменений|
64 | |git add| Добавить указанные файлы в список отслеживаемых|
65 | |git add \*| Добавить все файлы|
66 | |git rm| Удалить файлы|
67 | |git commit -m| Закоммитить изменения; после -m в кавычках пишется сообщение о том, что изменено|
68 | |git push| Отправить изменения в удаленный репозиторий|
69 | |git log| Посмотреть журнал действий|
70 |
71 | Более продвинутые вещи -- например, как исправлять ошибки или как работать с разными ветками -- можно почитать в [пошаговом тьюториале](https://git-scm.com/book/en/v1/Git-Basics-Undoing-Things) на официальном сайте.
72 |
--------------------------------------------------------------------------------
/Lessons/JSON/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "абв": 1,
3 | "где": 2,
4 | "ёжз": 3
5 | }
--------------------------------------------------------------------------------
/Lessons/Markdown и git/DS_Store-gitignore.md:
--------------------------------------------------------------------------------
1 | # Про .DS_Store
2 | Специально для счастливых обладателей машин на Mac OS X :)
3 |
4 | ## Что это такое?
5 | Возможно, когда вы коммитили ваши файлы и папки через командную строку, вместе с тем, что вы _ожидали_ увидеть (папки и файлы), в репозитории вы увидели странный файл, который называется ```.DS_Store```. Не исключено, что вы уже начали нервничать по этому поводу.
6 |
7 | ```.DS_Store``` — это **системный** файл, в котором лежат пользовательские настройки текущей папки в духе "какие иконки использовать" и "как сортировать файлы в папке" (а сам DS_Store расшифровывается как _Desktop Service Store_). Его создаёт система, чтобы папка каждый раз выглядела именно так, как вы хотите.
8 |
9 | Обычно вы не видите этот файл. Это происходит, потому что Mac OS X скрывает от пользователя все файлы и директории, которые начинаются с точки (а это как раз про DS_Store). Такие файлы называются **скрытыми**.
10 |
11 | Когда мы создаём коммит, мы используем строку типа ```git add *``` или ```git add .```, то есть добавляем в коммит _все_ файлы (и подпапки текущей папки, если используем вариант со звёздочкой), включая скрытые. Поэтому в репозитории и отображается ```.DS_Store```.
12 |
13 | ## Как убрать .DS_Store из репозитория?
14 | Для этого воспользуемся удобной штукой, которая называется _gitignore_. Она позволяет указать файлы и папки, которые не нужно коммитить (что, на самом деле, вытекает из её названия: _git_ + _ignore_ :)
15 |
16 | ### Своими руками
17 | Откройте любой текстовый редактор и пропишите в нём **пути** к файлам и папкам, которые вы не хотите коммитить. Один файл/папка = одна строка. Это должно выглядеть примерно так:
18 |
19 | 
20 | _Я использую Sublime Text_
21 |
22 | После этого сохраните этот файл в папке, из которой коммитите в репозиторий. Дайте ему имя ```.gitignore``` (да-да, именно так, начиная с точки!).
23 |
24 | 
25 |
26 | Система предупредит вас о том, что вы собираетесь создать скрытый файл, который не будет видно. Мы теперь прошаренные и знаем, что так бывает, поэтому уверенно (принимаем условия данного лицензионного соглашения) нажимаем, что хотим начать с точки.
27 |
28 | 
29 |
30 | Создайте коммит (```git add```, ```git commit```, всё как всегда) и запушьте (```git push```) его в ваш репозиторий. Не забудьте дать коммиту осмысленное сообщение.
31 |
32 | Готово, вы восхитительны!
33 |
34 | ### Автоматически (при создании репозитория)
35 | При создании репозитория вы можете использовать ```.gitignore```, который заранее собран усилиями тех, кто уже кодил на том или ином языке программирования. Это поможет не коммитить лишний "мусор", который возникает при запуске программ.
36 |
37 | При создании репозитория найдите в списке нужный вам язык и кликните по нему (можно использовать поиск).
38 |
39 | 
40 |
41 | _Внимание на левый нижний угол_
42 |
43 | Готово, вы восхитительны!
44 |
45 | > Важно: уже созданный gitignore можно и нужно редактировать, если вам это нужно.
46 |
47 | ## Как настроить систему так, чтобы скрытые файлы отображались?
48 |
49 | Следуйте [инструкции](https://ochprosto.com/kak-pokazat-skrytye-fajly-na-mac-os/). Если она вам не нравится, загуглите "отображение скрытых файлов mac os x" :)
50 |
51 | *Дарья Максимова*
--------------------------------------------------------------------------------
/Lessons/Markdown и git/Markdown.md:
--------------------------------------------------------------------------------
1 | ## Markdown
2 |
3 | **Markdown** -- это упрощенный язык разметки, который преобразует \(почти\) обычный текст в html-страницу. Создан в 2004 году Джоном Грубером и Аароном Шварцем, затем был дополнен и адаптирован для различных приложений.
4 |
5 | Markdown-файлы имеют расширение .md или .markdown
6 |
7 | Ниже в серых блоках содержится то, как выглядит текст на стадии разметки, сразу после блока находится результат.
8 |
9 | #### 1. Форматирование в Markdown
10 |
11 | Заголовки в Markdown выделяются решетками \#:
12 |
13 | \# заголовок 1 уровня
14 | \#\# заголовок 2 уровня
15 | ...
16 | \#\#\#\#\#\# заголовок 6 уровня
17 |
18 | Чтобы выделить текст курсивом, нужно поставить в начале и в конце фрагмента текста \* или \_ \(не отделяя пробелом\):
19 |
20 | ```
21 | *звезды* или _нижние подчеркивания_
22 | ```
23 |
24 | _звезды_ или _нижние подчеркивания_
25 |
26 | Чтобы сделать текст жирным, нужно поставить в начале и в конце фрагмента текста \*\* или \_\_ \(не отделяя пробелом\):
27 |
28 | ```
29 | **две звезды** или __два нижних подчеркивания__
30 | ```
31 |
32 | **две звезды** или **два нижних подчеркивания**
33 |
34 | Чтобы перечеркнуть текст, используйте ~~ в начале и в конце \(не отделяя пробелом\):
35 |
36 | ```
37 | ~~две тильды~~
38 | ```
39 |
40 | ~~две тильды~~
41 |
42 | ###### Списки
43 |
44 | Нумерованные списки задаются так \(уровни можно задать отступами\):
45 |
46 | ```
47 | 1. первый элемент
48 | 2. второй элемент
49 | 3. третий элемент
50 | 4. четвертый элемент
51 | 1. пятый элемент
52 | ```
53 |
54 | 1. первый элемент
55 | 2. второй элемент
56 | 3. третий элемент
57 | 4. четвертый элемент
58 | 5. пятый элемент
59 |
60 | Маркированные списки задаются с помощью дефисов, астерисков или плюсов \(уровни можно задать отступами\):
61 |
62 | ```
63 | + первый элемент
64 | - второй элемент
65 | + третий элемент
66 | - четвертый элемент
67 | * пятый элемент
68 | ```
69 |
70 | * первый элемент
71 | * второй элемент
72 | * третий элемент
73 | * четвертый элемент
74 | * пятый элемент
75 |
76 | #### 2. Объекты
77 |
78 | ###### Ссылки
79 |
80 | Ссылки и адреса электронной почты можно вставить без всего или в угловых скобках:
81 |
82 | ```
83 |
84 | https://www.markdownguide.org
85 |
86 |
87 | eee@mail.ru
88 | ```
89 |
90 | [https://www.markdownguide.org](https://www.markdownguide.org)
91 | [https://www.markdownguide.org](https://www.markdownguide.org)
92 |
93 | [eee@mail.ru](mailto:eee@mail.ru)
94 | eee@mail.ru
95 |
96 | Если нужно сделать гиперссылку, то она оформляется так:
97 |
98 | ```
99 | [текст](https://www.markdownguide.org)
100 | ```
101 |
102 | [текст](https://www.markdownguide.org)
103 |
104 | Можно добавить всплывающий при наведении комментарий:
105 |
106 | ```
107 | [текст](https://www.markdownguide.org "это поможет")
108 | ```
109 |
110 | [текст](https://www.markdownguide.org "это поможет")
111 |
112 | ###### Картинки
113 |
114 | Чтобы вставить картинку, нужно написать следующую строку \(без пробелов\):
115 |
116 | !\[\]\(ссылка на картинку\)
117 |
118 | Например:
119 |
120 | ```
121 | 
122 | ```
123 |
124 | 
125 |
126 | ###### Таблицы
127 |
128 | Строки в таблице разделяются переходом на новую строку, столбцы вертикальной чертой \(\|\)
129 | Между заголовком и телом таблицы вставляется строка с --- в каждой ячейке. Выравнивание задается положением двоеточия:
130 |
131 | ```
132 | 1|2|3
133 | ---|:---:|---:
134 | да|нет|не знаю
135 | не знаю|нет|да
136 | нет|не знаю|да
137 | нет|да|не знаю
138 | да|не знаю|нет
139 | не знаю|да|нет
140 | ```
141 |
142 | | 1 | 2 | 3 |
143 | | :--- | :---: | ---: |
144 | | да | нет | не знаю |
145 | | не знаю | нет | да |
146 | | нет | не знаю | да |
147 | | нет | да | не знаю |
148 | | да | не знаю | нет |
149 | | не знаю | да | нет |
150 |
151 | #### 3. Где можно использовать Markdown?
152 |
153 | * GitHub
154 | * Telegram
155 | * Tumblr
156 | * R, Python ...
157 |
158 | #### 4. Полезные \(и не очень\) ссылки
159 |
160 | [Изначальная страница проекта](https://daringfireball.net/projects/markdown/syntax) \(сейчас неактивна\)
161 | [Наиболее полное руководство](https://www.markdownguide.org)
162 | [Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Here-Cheatsheet) \(сжатый конспект\)
163 | [Help от гитхаба](https://help.github.com/categories/writing-on-github/)
164 | [Фичи для продвинутых от гитхаба](https://guides.github.com/features/mastering-markdown/)
165 | [Вдохновляющий набор расширений и приложений, где используется Markdown](https://github.com/mundimark/awesome-markdown) \(там есть, в том числе, про то, как делать презентации и документы, а также писать красивые письма\)
166 | [Курс на codeacademy](https://www.codecademy.com/en/courses/web-intermediate-en-Bw3bg/0/1)
167 |
168 |
--------------------------------------------------------------------------------
/Lessons/Markdown и git/cmd cheatsheet.md:
--------------------------------------------------------------------------------
1 | **Командная строка** - это такое окошко, куда можно вписать команду, и компьютер ее выполнит. На Windows она называется cmd, на Linux - Terminal. В командной строке вы увидите свое текущее местоположение (например, `ancatmara@INGEN C:\Users\ancatmara`), а на следующей строке - особый символ, который означает, что можно вводить команду. На Windows это **>**, а на Linux - **$**.
2 |
3 | Стандартный терминал cmd на Windows очень неудобный, так что можно выбрать и установить альтернативный вариант, [прочитав вот эту статью](https://habrahabr.ru/post/164687/).
4 |
5 | ## Самые главные команды в командной строке Windows и Linux
6 |
7 | | Значение | Windows | Linux / MacOS |
8 | | ------------- |-------------:| -----:|
9 | | Переход в другую директорию | cd | cd |
10 | | Создание файла | copy con | touch|
11 | | Создание папки | mkdir | mkdir |
12 | | Удаление файла | del, erase | rm; rm -rf -- удалить папку и все файлы в ней |
13 | | Удаление папки | rmdir | rmdir |
14 | | Вывод на экран сообщения | echo | echo |
15 | | Вывод на экран содержимого файла | type | cat|
16 | | Копирование файлов | copy, xcopy | cp |
17 | | Переименование файлов | ren, rename | mv |
18 | | Перемещение файлов | move | mv |
19 | | Поиск файлов | where | find, locate |
20 | | Вывод списка файлов и каталогов| dir | ls, dir |
21 | | Помощь | help | apropos, man, whatis |
22 |
23 |
24 | **Циркумфлекс** (вот этот знак "^") означает нажатие клавиши с Ctrl (^C = Ctrl + C).
25 |
26 | ^C — Прерывает команду, ну это все знают.
27 |
28 | ^S — Приостанавливает выполнение команды, а потом запускает.
29 |
30 | ^I — Аналог Tab, перебирает папки и файлы.
31 |
32 | ^M — Аналог Enter.
33 |
34 | ^H — Аналог Backspace.
35 |
36 | ## Работа с Python
37 |
38 | |Команда| Значение|
39 | |-------| -------:|
40 | |python| Запустить питон в терминале |
41 | |python --version| Посмотреть версию питона|
42 | |pip freeze| Посмотреть список установленных пакетов|
43 | |pip install| Установить пакет|
44 | |pip uninstall| Удалить пакет|
45 | |pip show| Показать информацию о конкретном пакете|
46 | |pip search| Найти пакет (если вы хотите установить что-то новое, но точно не помните название)|
47 |
48 | Подробнее про работу с pip можно почитать [на официальном сайте с документацией](https://pip.pypa.io/en/stable/).
49 |
50 | Если у вас установлена Анаконда, то вы можете пользоваться аналогом pip, который называется conda. Для него есть свой собсвенный [cheatsheet](https://conda.io/docs/_downloads/conda-cheatsheet.pdf) и [сайт с документацией](https://conda.io/docs/index.html).
51 |
52 | **NB!** Если команды python и pip не работают, вернитесь к [семинару про настройку окружения](https://github.com/ancatmara/learnpython2018/blob/master/Lessons/1/1.%20Intro.ipynb).
53 |
54 | ## Работа с Git
55 |
56 | У git очень много возможностей, и про работу с ним написаны толстые книжки (см. пример ниже :D). Здесь перечислены только самые часто употребляемые команды.
57 |
58 | |Команда| Значение|
59 | |-------| -------:|
60 | |git clone| Склонировать репозиторий по указанной ссылке|
61 | |git pull| Скачать изменения из удаленного репозитория|
62 | |git init| Создать репозиторий |
63 | |git status| Посмотреть статус изменений|
64 | |git add| Добавить указанные файлы в список отслеживаемых|
65 | |git add \*| Добавить все файлы|
66 | |git rm| Удалить файлы|
67 | |git commit -m| Закоммитить изменения; после -m в кавычках пишется сообщение о том, что изменено|
68 | |git push| Отправить изменения в удаленный репозиторий|
69 | |git log| Посмотреть журнал действий|
70 |
71 | Более продвинутые вещи -- например, как исправлять ошибки или как работать с разными ветками -- можно почитать в [пошаговом тьюториале](https://git-scm.com/book/en/v1/Git-Basics-Undoing-Things) на официальном сайте.
72 |
73 | **NB!** Чтобы не печатать длинные пути целиком, существует *автозаполнение*: набираете 1-2 первые буквы, нажимаете tab и вуаля!
74 |
75 | ### Как настроить авторизацию в Git?
76 |
77 | После установки git необходимо его настроить, это делается с помощью двух команд:
78 |
79 | `git config --global user.name "ваш логин на github"`
80 |
81 | `git config --global user.email "почту, которую указали при регистрации на GitHub.com"`
82 |
83 | ### Vim
84 |
85 | В некоторых случаях -- например, если напишете просто `git commit`, а не `git commit -m`, вы попадете в страшное место под названием `vim`, из которого очень сложно выбраться. Да-да, один из самых популярных запросов на Stackoverflow -- ["How to exit the Vim editor"](https://stackoverflow.com/questions/11828270/how-to-exit-the-vim-editor).
86 |
87 |
88 |
89 | 
90 |
91 | Vim -- это текстовый редактор внутри командной строки. При попадании в него вы увидите пустой файл или файл, где строки начинаются с #. Нажатие на i (язык раскаладки клавиатуры имеет значение) переводит в режим редактирования (внизу появилось --INSERT--), теперь вы можете написать подпись, когда закончили писать, нажимайте клавишу Esc [полное название - Escape] (--INSERT-- пропадет), теперь надо написать :wq (w - write, q - quit, эти три символа должны отобращзиться там же, где было --INSERT--) и нажать Enter. Поздравляю, вы выбрались из тюрьмы! (:w - сохраняет файл, но не выходит из редактора; :q - выходит из файла, если он не изменился с последнего сохранения; :q! - отменить изменения после последнего сохранения;` [http://vim.wikia.com/wiki/Undo_and_Redo](http://vim.wikia.com/wiki/Undo_and_Redo/) `)`
92 |
93 | 
94 |
95 | Vim – сложный, но предалагается по умолчанию (а на MacOS и Linux выбрать иное не дают), да и на компьютерах на Старой Басманной он используется.
96 |
--------------------------------------------------------------------------------
/Lessons/Markdown и git/deadline.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ancatmara/learnpython2018/eec59d8a9d05ca80783d39963189cbd80ac661f3/Lessons/Markdown и git/deadline.jpg
--------------------------------------------------------------------------------
/Lessons/Telegram-боты/bot_example/bot.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import telebot
3 | import conf
4 | import random
5 | import shelve
6 | from telebot import types
7 |
8 | bot = telebot.TeleBot(conf.TOKEN, threaded=False)
9 |
10 | with open('reviews.csv', 'r', encoding='utf-8') as f:
11 | reviews = {}
12 | for line in f:
13 | num, text = line.strip().split('\t')
14 | reviews[num] = text
15 | review_keys = list(reviews.keys())
16 |
17 | keyboard = types.ReplyKeyboardMarkup(row_width=3)
18 | btn1 = types.KeyboardButton('+')
19 | btn2 = types.KeyboardButton('-')
20 | btn3 = types.KeyboardButton('=')
21 | keyboard.add(btn1, btn2, btn3)
22 |
23 | shelve_name = 'shelve.db' # Файл с хранилищем
24 |
25 |
26 | def set_user_review(chat_id, review):
27 | """
28 | Записываем юзера в игроки и запоминаем, что он должен ответить.
29 | :param chat_id: id юзера
30 | :param estimated_answer: правильный ответ (из БД)
31 | """
32 | with shelve.open(shelve_name) as storage:
33 | storage[str(chat_id)] = review
34 |
35 |
36 | def finish_user_review(chat_id):
37 | """
38 | Заканчиваем игру текущего пользователя и удаляем правильный ответ из хранилища
39 | :param chat_id: id юзера
40 | """
41 | with shelve.open(shelve_name) as storage:
42 | del storage[str(chat_id)]
43 |
44 |
45 | def get_user_review(chat_id):
46 | """
47 | Получаем правильный ответ для текущего юзера.
48 | В случае, если человек просто ввёл какие-то символы, не начав игру, возвращаем None
49 | :param chat_id: id юзера
50 | :return: (str) Правильный ответ / None
51 | """
52 | with shelve.open(shelve_name) as storage:
53 | try:
54 | review = storage[str(chat_id)]
55 | return review
56 | # Если человек не играет, ничего не возвращаем
57 | except KeyError:
58 | return None
59 |
60 |
61 | # этот обработчик запускает функцию send_welcome, когда пользователь отправляет команды /start или /help
62 | @bot.message_handler(commands=['help'])
63 | def send_welcome(message):
64 | bot.send_message(message.chat.id,
65 | "Здравствуйте! Это бот для разметки отзывов на кинофильмы.\n Положительные отзывы отмечаются плюсом +, отрицательные минусом -, а нейтральные знаком равно =.")
66 |
67 |
68 | @bot.message_handler(commands=['start'])
69 | def send_first_review(message):
70 | review_num = random.choice(review_keys)
71 | bot.send_message(message.chat.id, reviews[review_num], reply_markup=keyboard)
72 | set_user_review(message.chat.id, review_num)
73 |
74 |
75 | @bot.message_handler(regexp='[-+=]') # этот обработчик реагирует на символы разметки
76 | def get_answer(message):
77 | review_num = get_user_review(message.chat.id)
78 | if review_num:
79 | with open('results.csv', 'a', encoding='utf-8') as results:
80 | results.write(review_num + '\t' + message.text + '\n')
81 | review_num = random.choice(review_keys)
82 | bot.send_message(message.chat.id, reviews[review_num], reply_markup=keyboard)
83 | set_user_review(message.chat.id, review_num)
84 | else:
85 | bot.send_message(message.chat.id, 'Вы не разметили отзыв.')
86 |
87 |
88 | if __name__ == '__main__':
89 | bot.polling(none_stop=True)
--------------------------------------------------------------------------------
/Lessons/Telegram-боты/bot_example/results.csv:
--------------------------------------------------------------------------------
1 | 5 +
2 | 3 =
3 | 4 -
4 | 5 +
5 | 10 -
6 | 4 -
7 | 1 -
8 | 3 -
9 | 5 +
10 | 4 -
11 | 8 =
12 | 8 =
13 | 3 -
14 | 9 +
15 | 9 +
16 | 4 -
17 | 8 +
18 | 7 =
19 | 3 -
20 | 7 =
21 | 3 =
22 | 4 -
23 | 5 +
24 | 10 -
25 | 8 +
26 | 2 +
27 | 4 -
28 | 9 +
29 | 7 =
30 | 2 +
31 | 4 -
32 | 5 +
33 | 9 +
34 | 4 -
35 | 4 -
36 | 7 -
37 | 2 +
38 | 6 +
39 | 8 +
40 | 3 =
41 | 7 +
42 | 10 -
43 | 4 -
44 |
--------------------------------------------------------------------------------
/Lessons/Telegram-боты/bot_example/reviews.csv:
--------------------------------------------------------------------------------
1 | 1 Скучно и примитивно...
2 | 2 Зря так пугают !Мне мультик был мил и даже приятен. Для двд дома сойдёт!Есть фильмы попустее ))...
3 | 3 В детстве была фанатом серии книг Волкова о девочке Элли. Ожидала чего-то ближе к тексту. Поэтому и разочаровалась, наверное, в "современной" версии. Обычный , ничем не примечательный детский мульт, коих штампуется множество ежедневно....
4 | 4 Плохо...
5 | 5 Супер! Мне показалось что он даже лучше первой части, сами съемки широкоформатные просто как в жизни , 3D эффект тоже хорошо сделан правда в динамических сценах не до него , юмор простой , фильм смотрится легко и не жаль ни времени ни денег, буду рекомендовать всем друзьям. Вот почему его не реклами...
6 | 6 Отличный фильм, сильнее первой части. Юмор, экшн, игра актеров - все на высшем уровне....
7 | 7 Да уж, такого трешака от Марвел я еще не видел... В целом, конечно, графика космическая (в прямом и переносном смысле), бабла на нее не пожалели, да и технологии видно шагают вперед, все уже как настоящее. Плюс в фильме неплохое 3д. Но.. что это было??? Весь фильм они друг с другом рубятся, юморят, ...
8 | 8 Нормуль. Своеобразная трактовка легенды. Запомнился побег в лондиниуме. Музыка норм. Спец. Эффекты супер. Юмор присутствует....
9 | 9 Здравствуйте!Фильм "Дом летающих кинжалов " понравился. Несравненная актриса Чжан Цзыи, чьи роли замечательные.Спасибо.Порадовали....
10 | 10 не тратте своё время...
--------------------------------------------------------------------------------
/Lessons/Telegram-боты/reviews.csv:
--------------------------------------------------------------------------------
1 | 1 Скучно и примитивно...
2 | 2 Зря так пугают !Мне мультик был мил и даже приятен. Для двд дома сойдёт!Есть фильмы попустее ))...
3 | 3 В детстве была фанатом серии книг Волкова о девочке Элли. Ожидала чего-то ближе к тексту. Поэтому и разочаровалась, наверное, в "современной" версии. Обычный , ничем не примечательный детский мульт, коих штампуется множество ежедневно....
4 | 4 Плохо...
5 | 5 Супер! Мне показалось что он даже лучше первой части, сами съемки широкоформатные просто как в жизни , 3D эффект тоже хорошо сделан правда в динамических сценах не до него , юмор простой , фильм смотрится легко и не жаль ни времени ни денег, буду рекомендовать всем друзьям. Вот почему его не реклами...
6 | 6 Отличный фильм, сильнее первой части. Юмор, экшн, игра актеров - все на высшем уровне....
7 | 7 Да уж, такого трешака от Марвел я еще не видел... В целом, конечно, графика космическая (в прямом и переносном смысле), бабла на нее не пожалели, да и технологии видно шагают вперед, все уже как настоящее. Плюс в фильме неплохое 3д. Но.. что это было??? Весь фильм они друг с другом рубятся, юморят, ...
8 | 8 Нормуль. Своеобразная трактовка легенды. Запомнился побег в лондиниуме. Музыка норм. Спец. Эффекты супер. Юмор присутствует....
9 | 9 Здравствуйте!Фильм "Дом летающих кинжалов " понравился. Несравненная актриса Чжан Цзыи, чьи роли замечательные.Спасибо.Порадовали....
10 | 10 не тратте своё время...
--------------------------------------------------------------------------------
/Lessons/VK API/comment.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ancatmara/learnpython2018/eec59d8a9d05ca80783d39963189cbd80ac661f3/Lessons/VK API/comment.jpg
--------------------------------------------------------------------------------
/Lessons/VK API/post_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ancatmara/learnpython2018/eec59d8a9d05ca80783d39963189cbd80ac661f3/Lessons/VK API/post_cloud.png
--------------------------------------------------------------------------------
/Lessons/Базы данных/12. Базы данных.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Базы данных\n",
8 | "\n",
9 | "**Реляционная база данных** - это набор взаимосвязанных таблиц, в которых хранятся различные данные. **Строка** таблицы (row) содержит данные об одном объекте (например, о студенте), а **столбцы** таблицы (columns) описывают различные характеристики этих объектов — атрибутов (например, имя, курс, специальность, номер группы). Каждый столбец описывает только одну характеристику объекта и имеет *строго определенный тип данных*. Все стоки (записи) имеют одни и те же поля, только в них отображаются различная информация в зависимости от объекта. Вот так:\n",
10 | "\n",
11 | "|ФИО (строка)| Специальность (строка)| Курс (число)|\n",
12 | "| ------------- |-------------:| -----:|\n",
13 | "|Петя Иванов| филология| 1|\n",
14 | "|Вася Петров| физика| 2|\n",
15 | "|Маша Сидорова| биология| 3|\n",
16 | "\n",
17 | "В реляционной базе данных каждая таблица должна иметь **первичный ключ** (primary key) — поле или комбинацию полей, которые единственным образом идентифицируют каждую строку таблицы. Если ключ состоит из нескольких полей, он называется составным. Ключ должен быть уникальным и однозначно определять запись. По значению ключа можно отыскать единственную запись. Ключи служат также для упорядочивания информации в БД. По умолчанию это по умолчанию создающееся пое Id с порядковой нумерацией.\n",
18 | "\n",
19 | "Таблицы реляционной БД должны отвечать требованиям нормализации отношений. Нормализация отношений — это формальный аппарат ограничений на формирование таблиц, который позволяет устранить дублирование, обеспечивает непротиворечивость хранимых в базе данных, уменьшает трудозатраты на ведение базы данных.\n",
20 | "\n",
21 | "*Реляционные таблицы могут быть связаны друг с другом*, следовательно, данные могут извлекаться одновременно из нескольких таблиц. Таблицы связываются между собой для того, чтобы в конечном счете уменьшить объем БД. Связь каждой пары таблиц обеспечивается при наличии в них одинаковых столбцов.\n",
22 | "\n",
23 | "Существуют следующие типы информационных связей:\n",
24 | "* один-к-одному (one-to-one)\n",
25 | "* один-ко-многим (one-to-many)\n",
26 | "* многие-ко-многим (many-to-many)\n",
27 | "\n",
28 | "Связь **один-к-одному** предполагает, что одному атрибуту первой таблицы соответствует только один атрибут второй таблицы и наоборот. Связь **один-ко-многим** - это когда одному атрибуту первой таблицы соответствует несколько атрибутов второй таблицы. Связь **многие-ко-многим** - это когда одному атрибуту первой таблицы соответствует несколько атрибутов второй таблицы и наоборот. \n",
29 | "\n",
30 | "Для работы с БД используются специальные программы - они называются **Системами управления базами данных**, или **СУБД** (англ. *Database Management System, DBMS*). Существует множество СУБД, вот некоторые из них:\n",
31 | "\n",
32 | "* SQLite\n",
33 | "* MySQL\n",
34 | "* PostgreSQL\n",
35 | "* MongoDB\n",
36 | "* ...\n",
37 | "\n",
38 | "## SQL\n",
39 | "\n",
40 | "В названии нескольких СУБД встретилось сочетание SQL. Что это такое?\n",
41 | "\n",
42 | "**SQL** *(Structured Query Language)* - это особый язык для управления данными в БД. С помощью него можно добавлять, удалять, изменять и выбирать данные в таблицах. **Любое** обращение к базе данных называется **запросом**.\n",
43 | "\n",
44 | "SQL - очень простой язык. Нам потребуется лишь несколько команд для операций с данными (CREATE, DELETE, DROP, SELECT, INSERT, UPDATE) и команд-ограничителей для создания более точных запросов (WHERE, IN, AND, OR, NOT, BETWEEN, LIKE, LIMIT, OFFSET). Стоит обратить внимание, что порядок слов в запросе фиксирован: сначала идет \"что\", затем \"где\" и, наконец, \"с каким условием\".\n",
45 | "\n",
46 | "Для тренировки мы будем использовать интерактивный тьюториал SQLBolt.\n",
47 | "\n",
48 | "SELECT упражнения\n",
49 | "\n",
50 | "* https://sqlbolt.com/lesson/select_queries_introduction - основы (уроки 1-5, 8)\n",
51 | "* https://sqlbolt.com/lesson/select_queries_with_joins - выбор данных из нескольких таблиц (уроки 6-7)\n",
52 | "* https://sqlbolt.com/lesson/select_queries_with_expressions - работа с математическими выражениями\n",
53 | "\n",
54 | "\n",
55 | "DML упражнения\n",
56 | "\n",
57 | "* https://sqlbolt.com/lesson/inserting_rows\n",
58 | "* https://sqlbolt.com/lesson/updating_rows\n",
59 | "* https://sqlbolt.com/lesson/deleting_rows\n",
60 | "\n",
61 | "Создание и удаление таблиц (там же описаны типы данных)\n",
62 | "\n",
63 | "* https://sqlbolt.com/lesson/creating_tables (уроки 16-18)\n",
64 | "\n",
65 | "\n",
66 | "## Программы для работы с базами данных\n",
67 | "\n",
68 | "База данных -- это не текстовый формат, так что просто открыть его в блокноте и посмотреть, что внутри, не получится. Для этого существуют специальные программы.\n",
69 | "\n",
70 | "* [MySQL](https://www.mysql.com/)\n",
71 | "* [PostgreSQL](https://www.postgresql.org/)\n",
72 | "* [MongoDB](https://www.mongodb.com/)\n",
73 | "* [Firebird](https://firebirdsql.org/)\n",
74 | "\n",
75 | "[Вот тут](https://blog.capterra.com/free-database-software/) есть неплохое описание плюсов и минусов всего вышеперечисленного. \n",
76 | "\n",
77 | "\n",
78 | "## Базы данных и Python\n",
79 | "\n",
80 | "Питон позволяет работать с различными СУБД, но проще всего использовать встроенную библиотеку [SQLite](https://docs.python.org/3.5/library/sqlite3.html). Важно также запомнить, что файлы баз данных имеют расширение `.db`."
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": 31,
86 | "metadata": {},
87 | "outputs": [],
88 | "source": [
89 | "import sqlite3\n",
90 | "\n",
91 | "# подключаемся к базе данных\n",
92 | "conn = sqlite3.connect('example.db')\n",
93 | "\n",
94 | "# создаем объект \"курсор\", которому будем передавать запросы\n",
95 | "c = conn.cursor()\n",
96 | "\n",
97 | "# создаем таблицу\n",
98 | "c.execute(\"CREATE TABLE IF NOT EXISTS students(name text, major text, year integer)\")\n",
99 | "\n",
100 | "# вставляем строку\n",
101 | "c.execute(\"INSERT INTO students VALUES ('Петя Иванов','филология',1), ('Маша Петрова','история',4)\")\n",
102 | "\n",
103 | "# сохраняем изменения\n",
104 | "conn.commit()\n",
105 | "\n",
106 | "# отключаемся от БД\n",
107 | "#conn.close()"
108 | ]
109 | },
110 | {
111 | "cell_type": "markdown",
112 | "metadata": {},
113 | "source": [
114 | "**Важная вещь №1**: после подключения к БД нужно обязательно инициализировать курсор, иначе вы не сможете делать к ней запросы!\n",
115 | "\n",
116 | "**Важная вещь №2**: если вы что-то изменили, нужно обязательно закоммитить изменения, иначе они не сохранятся в файле БД!\n",
117 | "\n",
118 | "И немного о безопасности: при создании запроса нельзя использовать конкатенацию строк и форматирование строк, как в питоне. Это сделает ваше приложение уязвимым для SQL-инъекций - особых хакерских атак, которые заключаются в подставлении в запрос нежелательных комманд - например, DROP TABLE. Поподробнее об этом можно почитать [вот здесь](https://habrahabr.ru/post/148151/).\n",
119 | "\n",
120 | ""
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 18,
126 | "metadata": {},
127 | "outputs": [
128 | {
129 | "name": "stdout",
130 | "output_type": "stream",
131 | "text": [
132 | "('Петя Иванов', 'филология', 1)\n"
133 | ]
134 | }
135 | ],
136 | "source": [
137 | "# Так нельзя!\n",
138 | "name = 'Петя'\n",
139 | "c.execute(\"SELECT * FROM students WHERE name = '%s'\" % name)\n",
140 | "\n",
141 | "# Вот как надо\n",
142 | "x = ('Петя Иванов',)\n",
143 | "c.execute('SELECT * FROM students WHERE name=?', x)\n",
144 | "print(c.fetchone())"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": 53,
150 | "metadata": {},
151 | "outputs": [
152 | {
153 | "name": "stdout",
154 | "output_type": "stream",
155 | "text": [
156 | "('a', 1234.56, 4567.8)\n",
157 | "('u', 1111.1, 3333.3)\n",
158 | "('a', 1234.56, 4567.8)\n",
159 | "('u', 1111.1, 3333.3)\n"
160 | ]
161 | }
162 | ],
163 | "source": [
164 | "# Если результатом запроса является несколько строк, можно по ним итерировать\n",
165 | "\n",
166 | "for row in c.execute('SELECT * FROM students ORDER BY year'):\n",
167 | " print(row)"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "execution_count": 32,
173 | "metadata": {},
174 | "outputs": [],
175 | "source": [
176 | "# как подставить несколько переменных в sql-запрос\n",
177 | "\n",
178 | "x = 'Вася Пупкин'\n",
179 | "y = 'математика'\n",
180 | "z = 3\n",
181 | "\n",
182 | "c.execute('INSERT INTO students VALUES (?, ?, ?)', (x, y, z))\n",
183 | "conn.commit()"
184 | ]
185 | },
186 | {
187 | "cell_type": "markdown",
188 | "metadata": {},
189 | "source": [
190 | "#### Форматирование строк\n",
191 | "\n",
192 | "Если нужно подставить переменные в качестве названия таблицы или колонок, то придется использовать форматирование строк."
193 | ]
194 | },
195 | {
196 | "cell_type": "code",
197 | "execution_count": 48,
198 | "metadata": {},
199 | "outputs": [
200 | {
201 | "data": {
202 | "text/plain": [
203 | ""
204 | ]
205 | },
206 | "execution_count": 48,
207 | "metadata": {},
208 | "output_type": "execute_result"
209 | }
210 | ],
211 | "source": [
212 | "params = ['vowel', 'f1', 'f2']\n",
213 | "c.execute('CREATE TABLE vowels({}, {}, {})'.format(params[0], params[1], params[2]))"
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 51,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": [
222 | "# как написать длинный запрос посимпатичнее\n",
223 | "c.execute('''\n",
224 | "INSERT INTO vowels \n",
225 | "VALUES \n",
226 | "('a', 1234.56, 4567.8), \n",
227 | "('u', 1111.1, 3333.3)'''\n",
228 | ")"
229 | ]
230 | },
231 | {
232 | "cell_type": "code",
233 | "execution_count": 54,
234 | "metadata": {},
235 | "outputs": [
236 | {
237 | "name": "stdout",
238 | "output_type": "stream",
239 | "text": [
240 | "('a', 1234.56, 4567.8)\n",
241 | "('u', 1111.1, 3333.3)\n",
242 | "('a', 1234.56, 4567.8)\n",
243 | "('u', 1111.1, 3333.3)\n"
244 | ]
245 | }
246 | ],
247 | "source": [
248 | "for row in c.execute('SELECT * FROM vowels'):\n",
249 | " print(row)"
250 | ]
251 | },
252 | {
253 | "cell_type": "markdown",
254 | "metadata": {},
255 | "source": [
256 | "#### Функции курсора\n",
257 | "\n",
258 | "* **fetchone()** -- возвращает следующий элемент из результата запроса (т.е. одну строку из бд). Результат -- кортеж, где элементом является значение каждой из колонок или None\n",
259 | "* **fetchall()** -- возвращает все результаты запроса в виде списка\n",
260 | "* **fetchmany()** -- взвращает заданное количество строк из результатов запроса"
261 | ]
262 | },
263 | {
264 | "cell_type": "code",
265 | "execution_count": 35,
266 | "metadata": {},
267 | "outputs": [
268 | {
269 | "name": "stdout",
270 | "output_type": "stream",
271 | "text": [
272 | "('Петя Иванов', 'филология', 1)\n",
273 | "('Вася Пупкин', 'математика', 3)\n",
274 | "('Маша Петрова', 'история', 4)\n"
275 | ]
276 | }
277 | ],
278 | "source": [
279 | "# извлекаем строки по одной\n",
280 | "# обратите внимание, что после каждого вызова fetchone возвращает следующую строку!\n",
281 | "c.execute('SELECT * FROM students ORDER BY year')\n",
282 | "print(c.fetchone())\n",
283 | "print(c.fetchone())\n",
284 | "print(c.fetchone())"
285 | ]
286 | },
287 | {
288 | "cell_type": "code",
289 | "execution_count": 36,
290 | "metadata": {},
291 | "outputs": [
292 | {
293 | "name": "stdout",
294 | "output_type": "stream",
295 | "text": [
296 | "[('Петя Иванов', 'филология', 1), ('Вася Пупкин', 'математика', 3)]\n"
297 | ]
298 | }
299 | ],
300 | "source": [
301 | "# извлекаем две строки\n",
302 | "c.execute('SELECT * FROM students ORDER BY year')\n",
303 | "print(c.fetchmany(2))"
304 | ]
305 | },
306 | {
307 | "cell_type": "code",
308 | "execution_count": 37,
309 | "metadata": {},
310 | "outputs": [
311 | {
312 | "name": "stdout",
313 | "output_type": "stream",
314 | "text": [
315 | "[('Петя Иванов', 'филология', 1), ('Вася Пупкин', 'математика', 3), ('Маша Петрова', 'история', 4)]\n"
316 | ]
317 | }
318 | ],
319 | "source": [
320 | "# извлекаем все строки\n",
321 | "c.execute('SELECT * FROM students ORDER BY year')\n",
322 | "print(c.fetchall())"
323 | ]
324 | },
325 | {
326 | "cell_type": "markdown",
327 | "metadata": {},
328 | "source": [
329 | "### Задание\n",
330 | "\n",
331 | "1. Помните [таблицу с нанайскими гласными](https://github.com/ancatmara/learnpython2018/blob/master/Lessons/11/nanai-vowels.csv)? Давайте сделаем из не базу данных с помощью `sqlite3`.\n",
332 | "2. Теперь более реальная задача: возьмите за основу код сайта-анкеты из последнего домашнего задания и перепишите обработку данных. Ответы пользователя должны сохраняться не в сsv-таблицу, в базу данных и извлекаться из нее для отображения."
333 | ]
334 | }
335 | ],
336 | "metadata": {
337 | "kernelspec": {
338 | "display_name": "Python 3",
339 | "language": "python",
340 | "name": "python3"
341 | },
342 | "language_info": {
343 | "codemirror_mode": {
344 | "name": "ipython",
345 | "version": 3
346 | },
347 | "file_extension": ".py",
348 | "mimetype": "text/x-python",
349 | "name": "python",
350 | "nbconvert_exporter": "python",
351 | "pygments_lexer": "ipython3",
352 | "version": "3.6.7"
353 | }
354 | },
355 | "nbformat": 4,
356 | "nbformat_minor": 1
357 | }
358 |
--------------------------------------------------------------------------------
/Lessons/Веб-запросы и формы/8. Запросы и формы.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Запросы и формы\n",
8 | "\n",
9 | "## HTTP-запросы\n",
10 | "\n",
11 | "Вспомним первый семинар:\n",
12 | "\n",
13 | "> На самом деле, когда мы хотим открыть какую-то страницу в интернете, наш браузер отправляет на сервер запрос (\"Привет, сервер! я хочу код страницы по вот такому адресу!\"), а сервер затем отправляет ответ (\"Привет! Вот код страницы: ...\"). \n",
14 | "\n",
15 | "Такие запросы мы обычно отправляем по протоколу HTTP (протокол - просто набор правил отправки запроса). При отправке запроса нужно сказать серверу, как ему стоит обаботать наш запрос -- каким __методом__. Методы бывают разные, а сейчас мы разберем два основных: GET и POST.\n",
16 | "\n",
17 | "**GET**\n",
18 | "\n",
19 | "Этот метод является одним из самых распространенных и предназначен для получения требуемой информации и передачи данных в адресной строке. Пары «имя=значение» присоединяются в этом случае к адресу после вопросительного знака и разделяются между собой амперсандом (символ &). Удобство использования метода get заключается в том, что адрес со всеми параметрами можно использовать неоднократно, сохранив его, например, в закладки браузера, а также менять значения параметров прямо в адресной строке.\n",
20 | "\n",
21 | "**POST**\n",
22 | "\n",
23 | "Метод post посылает на сервер данные в запросе браузера. Это позволяет отправлять большее количество данных, чем доступно методу get, плюс эти данные можно скрывать. Большие объемы данных используются в форумах, почтовых службах, заполнении базы данных, при пересылке файлов и др.\n",
24 | "\n",
25 | "\n",
26 | "## HTML-формы\n",
27 | "\n",
28 | "В коде HTML-страницы можно написать веб-формы, которые генерируют запросы к какому-то ресурсу и отправляют их, используя какой-то метод.\n",
29 | "\n",
30 | "Чтобы создать форму используется тэг `\n",
55 | " \n",
56 | "\n",
57 | "Когда форма отправляется на сервер, управление данными передается программе, заданной атрибутом `action` тега `\n",
80 | "\n",
81 | " \n",
82 | " \n",
83 | " \n"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {},
89 | "source": [
90 | " \n",
91 | "__Вот пример c чекбоксами:__\n",
92 | "\n",
93 | " \n",
94 | " \n",
95 | " \n",
96 | " Чем вы любите заниматься\n",
97 | " \n",
98 | " \n",
99 | "\n",
100 | " \n",
113 | " \n",
114 | " \n",
115 | " \n",
116 | "Поподробнее про формы можно почитать [тут](https://www.w3schools.com/html/html_forms.asp). Ну и вообще на этом сайте есть тьюториалы по HTML, CSS и Bootstrap на все случаи жизни. :)"
117 | ]
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {},
122 | "source": [
123 | "## Percent encoding\n",
124 | "\n",
125 | "Мы уже говорили об особом способе кодирования символов в ссылках, когда обсуждали проект. Напомню, он называется percent encoding (потому что многие символы кодируются с использованием знака %), или URL encoding и подробно описан [вот тут](https://en.wikipedia.org/wiki/Percent-encoding). А [вот тут](https://www.w3schools.com/tags/ref_urlencode.asp) лежит таблица кодировки ASCII-символов. Есть специальные сайты, которые позволяют кодировать/декодировать текст с помощью percent encoding -- например, вот этот: https://www.url-encode-decode.com/ "
126 | ]
127 | },
128 | {
129 | "cell_type": "markdown",
130 | "metadata": {},
131 | "source": [
132 | "## Задания\n",
133 | "\n",
134 | "Посмотреть, как работает поиск в Google'e, Яндексе и Яндекс.Картах. Написать веб-страницу, с помощью которой можно искать слово там, там или там. Подсказка: сначала надо погуглить, что нужно прописать в \"action\", чтобы сделать редирект из формы на какую-то внешнюю веб-страницу.\n",
135 | "\n",
136 | "**Бонусное задание**\n",
137 | "\n",
138 | "Посмотреть, какие запросы отправляет какой-нибудь поисковик, когда ищет подсказки к введённым пользователем буквам, какие ответы он получает (там будет json), и написать программу, которая сама будет выдавать такие подсказки."
139 | ]
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {},
144 | "source": [
145 | "### Подсказка\n",
146 | "\n",
147 | "Самая простая форма, из которой напрямую делается редирект на какой-нибудь сайт -- например, поисковик -- будет выглядеть вот так. В `action` пишем адрес сайта, а в кажестве имени тега `` указываем то, как называется необходимый get-параметр. В Google'e параметр, через который передается поисковый запрос, называется `q`, а в Яндексе и Яндекс.Картах -- `text`."
148 | ]
149 | },
150 | {
151 | "cell_type": "markdown",
152 | "metadata": {},
153 | "source": [
154 | " \n",
155 | " \n",
156 | " \n",
157 | " Что ищем?\n",
158 | " \n",
159 | " \n",
160 | " \n",
165 | " \n",
166 | " \n"
167 | ]
168 | }
169 | ],
170 | "metadata": {
171 | "kernelspec": {
172 | "display_name": "Python 3",
173 | "language": "python",
174 | "name": "python3"
175 | },
176 | "language_info": {
177 | "codemirror_mode": {
178 | "name": "ipython",
179 | "version": 3
180 | },
181 | "file_extension": ".py",
182 | "mimetype": "text/x-python",
183 | "name": "python",
184 | "nbconvert_exporter": "python",
185 | "pygments_lexer": "ipython3",
186 | "version": "3.6.6"
187 | }
188 | },
189 | "nbformat": 4,
190 | "nbformat_minor": 1
191 | }
192 |
--------------------------------------------------------------------------------
/Lessons/Интерактивные визуализации/Интерактивные графики и карты в вебе.md:
--------------------------------------------------------------------------------
1 | # Интерактивные графики и карты в вебе, Google Charts, D3, geojson
2 |
3 | ## Введение
4 |
5 | Мы уже умеем строить статические графики с помощью matplotlib. Но если мы делаем веб-сервис, гораздо удобнее было бы представлять на сайте интерактивные графики, которые отзывались бы на жесты пользователя, то есть чтобы при наведении мыши появлялся бы какой-то дополнительный текст, линии подсвечивались, части графиков можно было бы перетаскивать. Со статическими картинками в форматах .png или .jpg это невозможно.
6 |
7 | Интерактивными элементы на веб-страницы делает специальный язык -- JavaScript, который мы в нашем курсе программирования не изучаем (потому что он не так хорошо умеет обрабатывать языковые массивы, как Python), но если мы хотим сделать веб-страницу красивой и функциональной, без JavaScript совсем нам не обойтись.
8 |
9 | Делать интерактивный график на чистом JavaScript (особенно без предварительного изучения языка) довольно сложно. Но у нас в руках есть инструменты, которые оказывают в этом существенную помощь -- это специальные подключаемые библиотеки для работы с графиками, прежде всего, Google Chart и d3.
10 |
11 | ## Google Chart
12 |
13 | [Здесь](https://developers.google.com/chart/interactive/docs/gallery) можно посмотреть на то, какие типы графиков можно встроить в интернет-страницу, используя Google Chart. [На самом деле таких типов гораздо больше](https://developers.google.com/chart/interactive/docs/more_charts).
14 |
15 | График встраивается в HTML довольно просто. Нужно всего лишь:
16 |
17 | 1. внутри тега `` поместить код подгрузки библиотеки: ``
18 | 2. внутри тега `` в нужном месте поместить код того слоя, в котором будет отображаться график. Размеры слоя можно регулировать:
19 | ``
20 | 3. выдать библиотеке данные, которые мы хотим отобразить на графике. Сделать это можно разными способами. Самое простое -- это зашить данные в коде JavaScript. Данные в нём представляется в очень похожем на питоновский синтаксисе:
21 |
22 | ```
23 | [
24 | ['Year', 'Sales', 'Expenses'],
25 | ['2004', 1000, 400],
26 | ['2005', 1170, 460],
27 | ['2006', 660, 1120],
28 | ['2007', 1030, 540]
29 | ]
30 | ```
31 | Знающий питон легко узнаёт в этом коде 5 массивов, вложенных в ещё один массив.
32 |
33 | Если поместить эту структуру внутрь JavaScript-функции, даже не очень разбираясь в принципах её действия, можно получить желаемый результат:
34 |
35 | ```
36 | function drawChart() {
37 | var data = google.visualization.arrayToDataTable([
38 | ['Year', 'Sales', 'Expenses'],
39 | ['2004', 1000, 400],
40 | ['2005', 1170, 460],
41 | ['2006', 660, 1120],
42 | ['2007', 1030, 540]
43 | ]);
44 | ```
45 |
46 | Получить из питона строку, которую можно было бы вставить внутрь JavaScript-кода, можно с помощью функции json.dumps() (вспомните, что и сам формат данных JSON появился благодаря языку JavaScript).
47 |
48 | ```
49 | import json
50 |
51 | js_function = 'function drawChart() { var data = google.visualization.arrayToDataTable({{data_to_display}});'
52 |
53 | data = [['Year', 'Sales', 'Expenses'], ['2004', 1000, 400], ['2005', 1170, 460], ['2006', 660, 1120], ['2007', 1030, 540]]
54 |
55 | data_for_visualization = json.dumps(data)
56 | js_function = js_function.replace('{{data_to_display}}', data_for_visualization)
57 |
58 | ```
59 | ## d3
60 |
61 | Другой способ создавать разнообразные интерактивные графики на веб-странице -- это библиотека d3.js. Галерея примеров того, что можно сделать с её помощью, [лежит здесь](https://github.com/d3/d3/wiki/Gallery). Как видно, возможности здесь практически безграничны, нужно только выбрать подходящий способ визуализации.
62 |
63 | [Здесь можно](https://www.jasondavies.com/wordcloud/) заранее сделать статическую картинку облака слов в svg (удобный для веба формат) и вставить её на ваш сайт. А [здесь](https://bl.ocks.org/mbostock/4062006) можно подсмотреть, как рисовать хордовую диаграмму, отражающую связи между группами объектов.
64 |
65 | Вообще-то d3 -- это очень мощный инструмент, с помощью которого можно создавать [свои достаточно сложные визуализации](https://github.com/d3/d3/blob/master/API.md), для этого просто нужно достаточно подробно [изучить устройство](https://github.com/d3/d3/wiki/Tutorials) библиотеки. Но если вам хватает уже существующих инструментов, можно воспользоваться ими в том же духе, как мы работали с Google Chart: взять готовый образец и подставить в него свои данные.
66 |
67 | ### Географические данные, GIS
68 |
69 | В d3 и Google Chart есть много способов отобразить географические данные и построить на них карту (интерактивную и отображаемую на интернет-странице). Более сложный (но в чём-то и более простой) и настраиваемый способ -- это использовать формат geojson.
70 |
71 | Для питона и этого формата есть [специальная библиотека](https://pypi.python.org/pypi/geojson), но она нужна в том случае, если работа с данными автоматизирована. Если же вы работаете с обозримым объёмом данных вручную, их можно сформировать на сайте [geojson.io](http://geojson.io/), он представляет собой простой визуальный редактор, в котором слева вы видите карту, а справа -- geojson. Когда вы отмечаете что-то слева, оно тут же автоматически появляется в этом самом формате справа.
72 |
73 | Например, мы можем поставить на карте какой-то маркер или нарисовать полигон, а щелчок по тому объекту, который мы добавили на карту, вызывает облачко с табличкой дополнительных признаков, которые можно прикрепить к маркеру. Например, в левой колонке таблички можно вписать слово `title`, а в той же строке справа название объекта ("метро Автозаводская" или что-то другое). Точно так же можно написать слева слово `description`, а справа что-то содержательное: "Лучшее место на свете!"
74 |
75 | Когда вы сделали таким образом свою карту в http://geojson.io/, нужно сохранить получившийся результат в виде файла с расширением .geojson
76 | Это можно сделать с помощью меню "Save" в левой верхней части экрана. Из предложенных вариантов нужно выбрать "GeoJSON".
77 |
78 | Если вы загрузите этот файл на github, то сайт по умолчанию будет не отображать содержимое файла, а сразу отрисовывать карту, как [вот тут](https://github.com/nevmenandr/DigitalHumanitiesMinorFeatures/blob/master/MoskowPetushkiWay.geojson). Правда, это работает только если geojson-файл не больше 10 мегабайт. Кроме того, такую карту можно вставить и на вашу страницу в Интернете, если в html-код вставить строку:
79 |
80 | ```
81 |
82 |
83 | ```
84 |
85 | Для примера выше эта строка будет выглядеть так:
86 |
87 | ```
88 |
89 | ```
90 |
91 | ## Задания
92 |
93 | 1. Нарисуйте с помощью Google Charts график, который мы рисовали с [matplotlib](https://github.com/ancatmara/learnpython2017/blob/master/%D0%A1%D0%B5%D0%BC%D0%B8%D0%BD%D0%B0%D1%80%D1%8B/13.%20Matplotlib.ipynb).
94 | 2. Нарисуйте карту, взяв данные из [WALS](http://wals.info/feature)
95 |
--------------------------------------------------------------------------------
/Lessons/Краулеры и парсинг веб-документов/4a. Urllib.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Семинар 1. Выкачиваем Интернет.\n",
8 | "\n",
9 | "## Введение\n",
10 | "Современный Интернет предоставляет лингвистам большое количество языковых данных: электронные газеты и журналы, блоги, форумы, социальные сети и т.д. Например, можно найти в сети много-много текстов и собрать корпус, или найти все газетные статьи и блог-посты про какую-нибудь корпорацию и проанализировать тональность сообщений. Сейчас мы научимся заниматься выкачиванием страниц из интернета с помощью Python.\n",
11 | "\n",
12 | "Для скачивания HTML-страниц в питоне есть специальный модуль **urllib.request**. \n",
13 | "\n",
14 | "## Минимальный пример\n",
15 | "Допустим, мы хотим скачать главную страницу Хабрахабра. \n",
16 | "На самом деле, когда мы хотим открыть какую-то страницу в интернете, наш браузер отправляет на сервер запрос (\"Привет, сервер! я хочу код страницы по вот такому адресу!\"), а сервер затем отправляет ответ (\"Привет! Вот код страницы: ...\").\n",
17 | "Чтобы получить страницу через питон, нужно сформировать запрос на сервер так же, как это делает браузер:"
18 | ]
19 | },
20 | {
21 | "cell_type": "code",
22 | "execution_count": 1,
23 | "metadata": {},
24 | "outputs": [],
25 | "source": [
26 | "import urllib.request # импортируем модуль \n",
27 | "req = urllib.request.Request('https://habrahabr.ru/')\n",
28 | "with urllib.request.urlopen(req) as response:\n",
29 | " html = response.read().decode('utf-8')"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "В переменной **req** у нас как раз находится запрос.\n",
37 | "Функция **urlopen** получает ответ сервера и скачивает страницу по ссылке https://habrahabr.ru/ в переменную **response**. **response** ведет себя как файл: например мы можем прочитать его содержимое с помощью **.read()** в другую переменную. \n",
38 | "Вот так просто мы сохранили код страницы в переменной **html**. Убедимся, что в там лежит html-код:"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 2,
44 | "metadata": {},
45 | "outputs": [
46 | {
47 | "name": "stdout",
48 | "output_type": "stream",
49 | "text": [
50 | "\n",
51 | "\n",
52 | " \n",
53 | " \n",
54 | "\n",
55 | "Лучшие публикации за сутки / \n"
56 | ]
57 | }
58 | ],
59 | "source": [
60 | "print(html[:210])"
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {},
66 | "source": [
67 | "Иногда сайт блокирует запросы, если их посылает не настоящий браузер с пользователем, а какой-то бот (например, так делает Гугл или Википедия). Иногда сайты присылают разные версии страниц, разным браузерам. \n",
68 | "По этим причинам полезно бывает писать скрипт, который умеет притворяться то одним, то другим браузером.\n",
69 | "Когда мы пытаемся получить страницу с помощью **urllib**, наш код по умолчанию честно сообщает серверу, что он является программой на питоне. Он говорит что-то вроде \"Привет, я Python-urllib/3.5\". \n",
70 | "Но можно, например, представиться Мозиллой:"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "execution_count": 3,
76 | "metadata": {},
77 | "outputs": [],
78 | "source": [
79 | "url = 'https://habrahabr.ru/' # адрес страницы, которую мы хотим скачать\n",
80 | "user_agent = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)' # хотим притворяться браузером\n",
81 | "\n",
82 | "req = urllib.request.Request(url, headers={'User-Agent':user_agent}) \n",
83 | "# добавили в запрос информацию о том, что мы браузер Мозилла\n",
84 | "\n",
85 | "with urllib.request.urlopen(req) as response:\n",
86 | " html = response.read().decode('utf-8')"
87 | ]
88 | },
89 | {
90 | "cell_type": "markdown",
91 | "metadata": {},
92 | "source": [
93 | "## Напоминание: как найти на странице что-нибудь\n",
94 | "Теперь предположим, что мы хотим выкачивать заголовки статей с главной страницы Хабрахабра. Код страницы у нас уже есть, но как из него что-то вытащить. Для начала нужно посмотреть в [исходник](view-source:https://habrahabr.ru/) и заметить, что заголовки хранятся в тэге **h2** с классом **post__title**. Заголовок выглядит примерно так:\n",
95 | "\n",
96 | "
']\n"
168 | ]
169 | }
170 | ],
171 | "source": [
172 | "print(titles[:3])"
173 | ]
174 | },
175 | {
176 | "cell_type": "markdown",
177 | "metadata": {},
178 | "source": [
179 | "Теперь давайте очистим заголовки от лишних переносов строк, лишних тэгов и распечатаем их подряд."
180 | ]
181 | },
182 | {
183 | "cell_type": "code",
184 | "execution_count": 10,
185 | "metadata": {},
186 | "outputs": [
187 | {
188 | "name": "stdout",
189 | "output_type": "stream",
190 | "text": [
191 | "Невыдуманные IT-истории о самозванцах и почему появились эти непонятные практики на собеседованиях\n",
192 | "Что происходит в рознице\n",
193 | "Делаем из Хабра торт. Снова\n",
194 | "Как поступить на PhD программу по машинному обучению\n",
195 | "Краткая история цифровой клавиатуры\n",
196 | "Frontend Conf — с заботой о пользователе\n",
197 | "Все люди не умеют писать код\n",
198 | "42-й протокол жизни, вселенной и всего такого: «напутственная речь»\n",
199 | "«У нас есть идеи для Maven 4 и даже Maven 5» — интервью с Robert Scholte, ключевым участником проекта Maven\n",
200 | "Деньги любят счёт: как машины сортируют купюры\n",
201 | "Использование Consul для масштабирования stateful-сервисов\n",
202 | "Топ-10 докладов Mobius 2018 Piter\n",
203 | "Антенна из пульверизатора: миниатюрность, гибкость и производительность\n",
204 | "Как расширять Kubernetes\n",
205 | "Горячая история техподдержки, или Почему AutoCAD удаляет прокси-объекты?\n",
206 | "Почему компилятор превратил мой цикл с условием в бесконечный?\n",
207 | "Дайджест событий для HR-специалистов в сфере IT на октябрь 2018\n",
208 | "ДНК. Механизмы хранения и обработки информации. Часть I\n"
209 | ]
210 | }
211 | ],
212 | "source": [
213 | "new_titles = []\n",
214 | "regTag = re.compile('<.*?>', re.DOTALL)\n",
215 | "regSpace = re.compile('\\s{2,}', re.DOTALL)\n",
216 | "for t in titles:\n",
217 | " clean_t = regSpace.sub(\"\", t)\n",
218 | " clean_t = regTag.sub(\"\", clean_t)\n",
219 | " new_titles.append(clean_t)\n",
220 | "for t in new_titles:\n",
221 | " print(t)"
222 | ]
223 | },
224 | {
225 | "cell_type": "markdown",
226 | "metadata": {},
227 | "source": [
228 | "Ну и осталось убрать некрасивые кусочки html, а именно заменить специальные html-последовательности nbsp и rarr на стрелочку, например."
229 | ]
230 | },
231 | {
232 | "cell_type": "code",
233 | "execution_count": 11,
234 | "metadata": {},
235 | "outputs": [
236 | {
237 | "name": "stdout",
238 | "output_type": "stream",
239 | "text": [
240 | "Невыдуманные IT-истории о самозванцах и почему появились эти непонятные практики на собеседованиях\n",
241 | "Что происходит в рознице\n",
242 | "Делаем из Хабра торт. Снова\n",
243 | "Как поступить на PhD программу по машинному обучению\n",
244 | "Краткая история цифровой клавиатуры\n",
245 | "Frontend Conf — с заботой о пользователе\n",
246 | "Все люди не умеют писать код\n",
247 | "42-й протокол жизни, вселенной и всего такого: «напутственная речь»\n",
248 | "«У нас есть идеи для Maven 4 и даже Maven 5» — интервью с Robert Scholte, ключевым участником проекта Maven\n",
249 | "Деньги любят счёт: как машины сортируют купюры\n",
250 | "Использование Consul для масштабирования stateful-сервисов\n",
251 | "Топ-10 докладов Mobius 2018 Piter\n",
252 | "Антенна из пульверизатора: миниатюрность, гибкость и производительность\n",
253 | "Как расширять Kubernetes\n",
254 | "Горячая история техподдержки, или Почему AutoCAD удаляет прокси-объекты?\n",
255 | "Почему компилятор превратил мой цикл с условием в бесконечный?\n",
256 | "Дайджест событий для HR-специалистов в сфере IT на октябрь 2018\n",
257 | "ДНК. Механизмы хранения и обработки информации. Часть I\n"
258 | ]
259 | }
260 | ],
261 | "source": [
262 | "for t in new_titles:\n",
263 | " print(t.replace(\" →\", \" -> \"))"
264 | ]
265 | },
266 | {
267 | "cell_type": "markdown",
268 | "metadata": {},
269 | "source": [
270 | "## Некоторые объяснения про регулярные выражения\n",
271 | "\n",
272 | "* Что такое `re.compile`?
\n",
273 | "Грубо говоря, `compile()` позволяет запомнить регулярное выражение и использовать его несколько раз. Суть в том, что перед тем как прогнать регулярку через строку, питон должен ее \"скомпилировать\" - превратить **строку** с регулярным выражением в специальный **объект**. \n",
274 | "Строчка `re.search(..., ...)` сначала компилирует регулярное выражение, а потом выполняет поиск. Если нужно поискать что-то один раз, то такая строчка очень удобна. А если нужно поискать что-то много раз, то получится что одно и то же выражение мы компилируем много раз. А хочется один раз скомпилировать и потом много раз пользоваться. Поэтому пишут так:"
275 | ]
276 | },
277 | {
278 | "cell_type": "code",
279 | "execution_count": null,
280 | "metadata": {
281 | "collapsed": true
282 | },
283 | "outputs": [],
284 | "source": [
285 | "text = 'тут текст, внутри которого мы что-то ищем'\n",
286 | "regName = re.compile('тут регулярное выражение') # скомпилировали\n",
287 | "toSearch = regName.search(text) # теперь можно искать в тексте\n",
288 | "toFindAll = regName.findall(text) # можно использовать скомпилированное выражение много раз\n",
289 | "toSub = regName.sub('на.что.заменить', text) # и так тоже можно использовать"
290 | ]
291 | },
292 | {
293 | "cell_type": "markdown",
294 | "metadata": {},
295 | "source": [
296 | "* Что делает `regName.sub(..., ...)`?
\n",
297 | "Выражение `regName.sub('на_что_заменить', text)` значит: возьми скомпилированное выражение из переменной `regName`, и замени все, что соответствует этому выражению в переменной `text`, на строку `'на_что_заменить'`. Если первый аргумент в этом случае - пустая строка, то все найденные регуляркой куски заменятся на пустую строку, короче говоря, удалятся.
\n",
298 | "\n",
299 | "* Что такое `re.DOTALL`?
\n",
300 | "Обычно точка в регулярном выражении означает любой символ КРОМЕ символа новой строки. Чтобы изменить такое поведение, в компиляцию регулярки можно добавить параметры-флаги вот так: `flags = re.DOTALL`, и тогда точка будет ловить вообще любой символ, включая новую строку. Эти флаги слегка меняют поведение функции, вот и все.
\n",
301 | "\n",
302 | "* Что такое `re.U`?
\n",
303 | "Про эту штуку нужно знать, если вы работаете с регулярками на втором питоне. Дело в том, что во втором питоне по умолчанию выражения типа `\\w`, `\\W`, `\\s` и подобные работают только на строках ASCII, и чтобы они работали на юникодных строках нужно поставить флаг re.U. В третьем питоне все строки и так юникодные, поэтому необходимости в таком флаге нет.\n"
304 | ]
305 | },
306 | {
307 | "cell_type": "markdown",
308 | "metadata": {},
309 | "source": [
310 | "## Задания\n",
311 | "\n",
312 | "1. Скачать главную страницу Яндекс.Погоды и \n",
313 | " \n",
314 | " а) распечатать сегодняшнюю температуру и облачность \n",
315 | " \n",
316 | " б) распечатать время восхода и заката \n",
317 | " \n",
318 | " в) погоду на завтра \n",
319 | " \n",
320 | "2. Скачать главную страницу waitbutwhy.com. Распечатать заголовки популярных постов (которые в колонке справа с надписью Popular Posts) и колличество комментариев у каждого из них."
321 | ]
322 | }
323 | ],
324 | "metadata": {
325 | "celltoolbar": "Raw Cell Format",
326 | "kernelspec": {
327 | "display_name": "Python 3",
328 | "language": "python",
329 | "name": "python3"
330 | },
331 | "language_info": {
332 | "codemirror_mode": {
333 | "name": "ipython",
334 | "version": 3
335 | },
336 | "file_extension": ".py",
337 | "mimetype": "text/x-python",
338 | "name": "python",
339 | "nbconvert_exporter": "python",
340 | "pygments_lexer": "ipython3",
341 | "version": "3.6.6"
342 | }
343 | },
344 | "nbformat": 4,
345 | "nbformat_minor": 1
346 | }
347 |
--------------------------------------------------------------------------------
/Lessons/Краулеры и парсинг веб-документов/4b. Краулеры.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Семинар 2. Выкачиваем Интернет (продолжение).\n",
8 | "\n",
9 | "Эпиграф: *У меня есть дома интернет. Можно я его скачаю на флешку и с собой принесу?*\n",
10 | "## Введение\n",
11 | "\n",
12 | "Мы научились скачивать из Интернета HTML-код страницы с заданным адресом. Это здорово, но на практике обычно приходится выкачивать содержимое не одной страницы, а целого сайта или даже многих сайтов --- тысячи или миллионы страниц. Понятно, что перечислить все интересующие нас адреса вручную, чтобы выкачать их по отдельности, в таком случае не получится. На этом семинаре мы выясним, как можно выкачивать страницы оптом, а также научимся получше их чистить от ненужных вещей.\n",
13 | "\n",
14 | "Основной проблемой, которую нужно решить при выкачивании большого количества страниц, --- как узнать адреса всех этих страниц. Мы рассмотрим два подхода.\n",
15 | "\n",
16 | "*Первый подход* обычно применяется, когда нужно загрузить все страницы какого-нибудь крупного ресурса --- например, газеты или форума. Адреса страниц на таких сайтах нередко устроены довольно просто: начинаются они все одинаково, а заканчиваются разными числами. Если внимательно посмотреть на адреса нескольких произвольных страниц, можно довольно быстро выяснить, так ли это и каков допустимый диапазон номеров страниц. В этом случае закачка всех страниц будет представлять собой простой цикл, в котором будут перебираться все номера страниц из этого диапазона.\n",
17 | "\n",
18 | "*Второй подход* обычно применяется в **краулерах** --- программах, которые обходят какой-то фрагмент интернета, собирая информацию с разных сайтов. Краулерами, например, пользуются поисковые системы, чтобы индексировать содержимое сайтов. Краулер начинает работу с одной или нескольких страниц, адреса которых задаются вручную, а затем переходит по всем ссылкам из этих страниц. Каждый раз, когда краулер загружает очередную страницу, он находит на ней не только нужную ему информацию, но и все ссылки, которые добавляются в очередь. Важно при этом помнить, где краулер уже побывал, чтобы не переходить по нескольку раз на одни и те же страницы. В настоящих краулерах применяют и другие ухищрения, например, чтобы выяснить, по каким ссылкам лучше переходить сначала, но мы этого касаться не будем.\n",
19 | "\n",
20 | "\n",
21 | "## Напоминание\n",
22 | "\n",
23 | "Ссылки в HTML задаются тэгом `a`, а сам адрес находится в атрибуте `href`. Ссылка обязательно должна начинаться с протокола (`http://`); если это не так, это означает, что ссылка указывает на другую страницу на том же сайте. При поиске ссылок в HTML нужно помнить, что между тэгом (`a`) и атрибутом (`href`) могут находиться другие атрибуты и любое количество пробелов.\n",
24 | "\n",
25 | "## Пример\n",
26 | "\n",
27 | "Чтобы было не так скучно, в этот раз мы будем тренироваться не на русском сайте, а на ирландском. Допустим, мы хотим скачать все статьи с http://dil.ie/ --- словаря древнеирландского языка. Если мы зайдем в Search и что-нибудь поищем, то словарь выдаст нам список статей с нашим запросом. В колонке слева будет заголовочное слово, а под ним --- прямая ссылка на словарную статью.\n",
28 | "\n",
29 | "Видно, что у них общее начало и у каждой страницы есть свой номер. Это значит, что мы можем пользоваться перебором номеров. Для этого нам достаточно узнать диапазон --- номера самой первой и самой последней страницы, в данном случае --- от 1 до 43345. Это мы оставляем в качестве упражнения читателю. В результате должно получиться что-то такое:\n"
30 | ]
31 | },
32 | {
33 | "cell_type": "code",
34 | "execution_count": 2,
35 | "metadata": {},
36 | "outputs": [],
37 | "source": [
38 | "import urllib.request\n",
39 | "\n",
40 | "def download_page(pageUrl):\n",
41 | " try:\n",
42 | " page = urllib.request.urlopen(pageUrl)\n",
43 | " text = page.read().decode('utf-8')\n",
44 | " except:\n",
45 | " print('Error at', pageUrl)\n",
46 | " return\n",
47 | " # do something with the downloaded text\n",
48 | "\n",
49 | "commonUrl = 'http://dil.ie/'\n",
50 | "for i in range(1, 10):\n",
51 | " pageUrl = commonUrl + str(i)\n",
52 | " download_page(pageUrl)"
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {},
58 | "source": [
59 | "В функции, отвечающей за загрузку, мы поместили собственно загрузку HTML в блок `try-except`. Это было сделано потому, что зачастую не всем номерам из допустимого диапазона соответствуют реальные страницы. Если страницы с таким адресом не существует, функция `urlopen` вызовет ошибку, которая благодаря `try-except` не вызовет падения всей программы.\n",
60 | "\n",
61 | "#### Замечание про кодировки\n",
62 | "\n",
63 | "Открывая веб-страницу, мы получаем всего лишь последовательность байт - чтобы увидеть текст, ее еще нужно расшифровать. За это отвечает метод `decode`, которому в качестве аргумента передается необходимая кодировка. Аргументом этой функции по умолчанию является \"utf-8\", но на многих русскоязычных сайтах, особенно старых, вы можете встретить кодировку \"cp1251\". \n",
64 | "\n",
65 | "## Важный комментарий\n",
66 | "\n",
67 | "Когда Ваша программа выкачивает много страниц сразу, она создаёт нагрузку на сервер выкачиваемого сайта --- и эта нагрузка намного больше, чем нагрузка от обычного посещения сайта людьми. Если Вы выкачиваете содержимое крупного сайта с одного компьютера, то ничего страшного в этом, скорее всего, нет. Но если это не какой-то крупный ресурс, который владеет мощными серверами, и тем более если страницы с него скачивают несколько человек одновременно, это может создать реальные проблемы владельцам выкачиваемого ресурса. Поэтому, во-первых, нужно всегда выяснять, не доступно ли всё содержимое нужного Вам ресурса по отдельной ссылке (например, так обстоит дело с Википедией), а во-вторых, ставить между обращениями к серверу искуственный временной интервал хотя бы в пару секунд:\n"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": 3,
73 | "metadata": {},
74 | "outputs": [],
75 | "source": [
76 | "import time\n",
77 | "\n",
78 | "time.sleep(2)"
79 | ]
80 | },
81 | {
82 | "cell_type": "markdown",
83 | "metadata": {},
84 | "source": [
85 | "## Как почистить текст\n",
86 | "\n",
87 | "В html странице, конечно, всегда много тэгов, скриптов и комментариев. А нам обычно бывает нужен только текст.\n",
88 | "Чтобы вытащить из html только текст, можно воспользоваться регулярными выражениями: "
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "execution_count": null,
94 | "metadata": {
95 | "collapsed": true
96 | },
97 | "outputs": [],
98 | "source": [
99 | "html_content = '....' # тут какой-то html\n",
100 | "\n",
101 | "regTag = re.compile('<.*?>', re.DOTALL) # это рег. выражение находит все тэги\n",
102 | "regScript = re.compile('', re.DOTALL) # все скрипты\n",
103 | "regComment = re.compile('', re.DOTALL) # все комментарии\n",
104 | "\n",
105 | "\n",
106 | "# а дальше заменяем ненужные куски на пустую строку\n",
107 | "clean_t = regScript.sub(\"\", t)\n",
108 | "clean_t = regComment.sub(\"\", clean_t)\n",
109 | "clean_t = regTag.sub(\"\", clean_t)"
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "metadata": {},
115 | "source": [
116 | "Нужно не забывать, что для отображения на html-странице символов, которых нет на клавиатуре, применяются специальные последовательности символов, начинающиеся с амперсанда (&) и заканчивающиеся точкой с запятой (;). Чтобы получить текст не с такими последовательностями, а с нормальными символами, используется специальная функция в питоне `unescape`:"
117 | ]
118 | },
119 | {
120 | "cell_type": "code",
121 | "execution_count": 4,
122 | "metadata": {},
123 | "outputs": [
124 | {
125 | "name": "stdout",
126 | "output_type": "stream",
127 | "text": [
128 | "Петя & Вася\n"
129 | ]
130 | }
131 | ],
132 | "source": [
133 | "# если у вас Python3.4+\n",
134 | "import html\n",
135 | "test_string = 'Петя & Вася'\n",
136 | "print( html.unescape(test_string) )"
137 | ]
138 | },
139 | {
140 | "cell_type": "code",
141 | "execution_count": 10,
142 | "metadata": {},
143 | "outputs": [
144 | {
145 | "name": "stdout",
146 | "output_type": "stream",
147 | "text": [
148 | "Специальные символы: \" « » ♠ ♥ ♣ ♦ и так далее\n"
149 | ]
150 | }
151 | ],
152 | "source": [
153 | "print( html.unescape('Специальные символы: " « » ♠ ♥ ♣ ♦ и так далее') )"
154 | ]
155 | },
156 | {
157 | "cell_type": "code",
158 | "execution_count": null,
159 | "metadata": {
160 | "collapsed": true
161 | },
162 | "outputs": [],
163 | "source": [
164 | "# если у вас Python3.3 или более ранняя версия \n",
165 | "import html.parser \n",
166 | "html.parser.HTMLParser().unescape('Петя & Вася')"
167 | ]
168 | }
169 | ],
170 | "metadata": {
171 | "celltoolbar": "Raw Cell Format",
172 | "kernelspec": {
173 | "display_name": "Python 3",
174 | "language": "python",
175 | "name": "python3"
176 | },
177 | "language_info": {
178 | "codemirror_mode": {
179 | "name": "ipython",
180 | "version": 3
181 | },
182 | "file_extension": ".py",
183 | "mimetype": "text/x-python",
184 | "name": "python",
185 | "nbconvert_exporter": "python",
186 | "pygments_lexer": "ipython3",
187 | "version": "3.6.6"
188 | }
189 | },
190 | "nbformat": 4,
191 | "nbformat_minor": 1
192 | }
193 |
--------------------------------------------------------------------------------
/Lessons/Краулеры и парсинг веб-документов/lxml_bs4.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "There are existing modules for parsing HTML. These are also not perfect, but they can often be a lot more perfect that you or I might have patience for;)"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "One very common solution in Python is **Beautiful Soup**, a free open-source module for Python for parsing and manipulating HTML. You have to install it yourself, but once installed, it can be called like any other module. The module is called **bs4** and the relevant function is `BeautifulSoup()`. What that does is parse the HTML and build a document model. This is a treelike representation of the HTML document and you can extract elements from it easily. The following code exemplifies:"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "#import for reading urls\n",
24 | "import urllib.request\n",
25 | "#import for parsing html\n",
26 | "from bs4 import BeautifulSoup\n",
27 | "#non-local page this time\n",
28 | "link = \"https://habr.com/\"\n",
29 | "#connect to that page\n",
30 | "f = urllib.request.urlopen(link)\n",
31 | "#read it all in\n",
32 | "myfile = f.read()\n",
33 | "#build a document model\n",
34 | "soup = BeautifulSoup(myfile,'html.parser')\n",
35 | "#print the page verbatim\n",
36 | "print(myfile)"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {},
42 | "source": [
43 | "Here we read in a web page and then parse it with `BeautifulSoup()`. We can then print a pretty version of it with `prettify()`, extract the text with `get_text()`, or find all instances of a tag with `find_all()`. Each tag found\n",
44 | "is its own treelike representation, so we can continue to call methods on them. In the example at hand, we call the `get()` method to extract the text of the `href` attribute for the `a` tags."
45 | ]
46 | },
47 | {
48 | "cell_type": "code",
49 | "execution_count": null,
50 | "metadata": {},
51 | "outputs": [],
52 | "source": [
53 | "#pretty-print the html\n",
54 | "print(soup.prettify())"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {},
61 | "outputs": [],
62 | "source": [
63 | "#extract the text\n",
64 | "print(soup.get_text())"
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "metadata": {},
71 | "outputs": [],
72 | "source": [
73 | "#got through all the hyperlinks...\n",
74 | "for link in soup.find_all('a'):\n",
75 | "#...and print them\n",
76 | " print(link.get('href'))"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": null,
82 | "metadata": {},
83 | "outputs": [],
84 | "source": [
85 | "import requests\n",
86 | "from bs4 import BeautifulSoup\n",
87 | "\n",
88 | "result = requests.get('https://habr.com/')\n",
89 | "html = result.text\n",
90 | "\n",
91 | "soup = BeautifulSoup(html,'html.parser')\n",
92 | "\n",
93 | "for post in soup.find_all('article', {'class': 'post'}):\n",
94 | " print(post.find('a', {'class': 'post__title_link'}).get_text())\n",
95 | " print(post.find('div', {'class': 'post__text'}).prettify())\n",
96 | "\n",
97 | " print('-- '*10)"
98 | ]
99 | },
100 | {
101 | "cell_type": "markdown",
102 | "metadata": {},
103 | "source": [
104 | "An alternative module for parsing HTML is **lxml**. It is quite easy to parse the HTML code extracted with the help of lxml. As soon as we trasformed our data into a tree, we can use XPath to extract them."
105 | ]
106 | },
107 | {
108 | "cell_type": "code",
109 | "execution_count": 1,
110 | "metadata": {},
111 | "outputs": [
112 | {
113 | "name": "stdout",
114 | "output_type": "stream",
115 | "text": [
116 | "Яндекс\n",
117 | "['https://mail.yandex.ru', '//yandex.ru']\n"
118 | ]
119 | }
120 | ],
121 | "source": [
122 | "import requests\n",
123 | "from lxml import html\n",
124 | "\n",
125 | "response = requests.get('http://ya.ru')\n",
126 | "\n",
127 | "# Преобразование тела документа в дерево элементов (DOM)\n",
128 | "parsed_body = html.fromstring(response.text)\n",
129 | "\n",
130 | "# Выполнение xpath в дереве элементов\n",
131 | "print(parsed_body.xpath('//title/text()')[0]) # Получить title страницы\n",
132 | "print(parsed_body.xpath('//a/@href')) # Получить аттрибут href для всех ссылок"
133 | ]
134 | }
135 | ],
136 | "metadata": {
137 | "kernelspec": {
138 | "display_name": "Python 3",
139 | "language": "python",
140 | "name": "python3"
141 | },
142 | "language_info": {
143 | "codemirror_mode": {
144 | "name": "ipython",
145 | "version": 3
146 | },
147 | "file_extension": ".py",
148 | "mimetype": "text/x-python",
149 | "name": "python",
150 | "nbconvert_exporter": "python",
151 | "pygments_lexer": "ipython3",
152 | "version": "3.6.5"
153 | }
154 | },
155 | "nbformat": 4,
156 | "nbformat_minor": 2
157 | }
158 |
--------------------------------------------------------------------------------
/Lessons/Морфологический анализ/6. Mystem.md:
--------------------------------------------------------------------------------
1 | # Семинар 3: Mystem
2 |
3 | 
4 |
5 | ## Запуск программ из командной строки
6 |
7 | Кроме программ, которые имеют GUI (графический, оконный интерфейс), часто приходится использовать такие программы, которые управляются из командной строки. Ещё она называется *терминалом* или *консолью*.
8 |
9 | Для того, чтобы запустить командную строку, в Windows нужно найти среди других программу **cmd**.
10 |
11 | В начале того, что показывает интерфейс командной строки, обычно написано, какое место в системе программа считает рабочим. Например, `C:\Users\student`. После этого обычно мы видим знак т.н. *приглашения* командной строки, то есть сигнал того, что программа готова к работе и ждёт действий от пользователя. В Windows это обычно знак *больше*, `>`.
12 |
13 | С помощью набора команд, которые отправляются на исполнение с помощью клавиши `Enter`, можно передвигаться по диску и запускать другие программы.
14 |
15 | Запуск программ обычно выглядит так. Сначала нужно написать путь к запускаемой программе: `C:\some_prog.exe`. Путь может быть и абсолютным, и относительным. Считается он относительно того места, которое показывается перед приглашением.
16 |
17 | Иногда программы нужно запускать не сами по себе, а с определёнными *аргументами* или ещё их называют *параметрами* (похоже на аргументы функции в питоне). Тогда эти аргументы пишутся после пути к программе через пробел. Если сам аргумент тоже содержит пробел, его нужно обернуть в кавычки: `C:\some_prog.exe argument1 "argument 2"`
18 |
19 | Кроме того, среди таких аргументов есть такие, которые принято называть *опциями* или *ключами*, они начинаются с символа дефиса: `C:\some_prog.exe -a -b`. Их можно "склеивать": `C:\some_prog.exe -ab`.
20 |
21 | Какие у программы возможны аргументы и опции, в каком порядке они должны идти при запуске из командной строки, обычно описано в документации к программам.
22 |
23 | Через командную строку можно, например, запускать скрипты на питоне. Тогда запускаемой программой будет интерпретатор питона, а аргументом -- путь к собственно скрипту: `C:\Python34\python.exe C:\myscript.py`
24 |
25 | ## Mystem
26 |
27 | Mystem - это свободно распространяемый морфологический анализатор для русского языка с закрытым исходным кодом. То есть мы можем его бесплатно скачать с сайта и пользоваться им, но не можем посмотреть, что у него внутри и как оно работает.
28 |
29 | Mystem был придуман одним из создателей Яндекса Ильёй Сегаловичем. Некоторый потомок mystem'а до сих пор работает внутри большого поисковика Яндекса, анализируя слова при поиске.
30 |
31 | My-stem значит my stemmer, стемминг -- это разбиение формы на основу и флексию. Но на самом деле Mystem может гораздо больше: устанавливать словарную форму слова, определять часть речи и грамматическую форму слова. В последних версиях Mystem умеет и выбирать из нескольких возможных грамматических разборов один, наиболее верный.
32 |
33 | У Mystem нет графического оконного интерфейса, запустить его можно только из командной строки.
34 |
35 | Скачать Mystem можно [отсюда](https://tech.yandex.ru/mystem/), а [тут](https://tech.yandex.ru/mystem/doc/index-docpage/) лежит его документация.
36 |
37 | Mystem не требует специальной инсталляции в систему. Достаточно, чтобы исполняемый файл с программой, подходящей для вашей версии операционной системы, находился на вашем компьютере.
38 |
39 | ## Как читать документацию Mystem
40 |
41 | [На странице документации](https://tech.yandex.ru/mystem/doc/index-docpage/) описаны разные возможности вызова Mystem из командной строки. В зависимости от параметров, с которыми мы вызовем программу, мы получим разный результат.
42 |
43 | Примеры, которые там приведены, рассчитаны на пользователя Unix-подобной операционной системы. То есть не Windows.
44 |
45 | В начале примеров вызова стоит знак доллара, $. Это не значит, что его вам тоже нужно набирать, если вы хотите воспроизвести эти примеры. Доллар -- это аналог приглашения командной строки, просто не в Windows, а в Unix-подобных системах. Если вы берете примеры вызова со страницы документации за основу, игнорируйте знак доллара.
46 |
47 | В документации написано: `$ mystem input`. На практике для пользователей Windows это будет значить что-то вроде `C:\mystem.exe input.txt`.
48 |
49 | В документации написано "стандартный ввод" и "стандартный вывод", это значит то, что вводится в командной строке или выводится в тот же терминал. Если не используются стандартный ввод и вывод, то используются файлы (выводной файл Mystem способен создать сам).
50 |
51 | В 3-й версии Mystem кодировка по умолчанию -- utf-8. В первых версиях -- cp1251. Кодировка по умолчанию в командной строке Windows -- cp866. Из-за этого Mystem может не понимать слова, которые попадают к нему из стандартного ввода.
52 |
53 | ## Как запускать Mystem
54 |
55 | Об этом довольно хорошо и подробно написано [на странице документации](https://tech.yandex.ru/mystem/doc/index-docpage/), её нужно внимательно изучить и попробовать разные вариант опций.
56 |
57 | Особое внимание нужно уделить опции `-d`, она заставляет анализатор выбирать только один разбор из возможных. При этом выбор происходит только между разными частями речи. Если у одной части речи возможны разные разборы (например, разные падежи одного и того же существительного), то эти разборы не отбрасываются. Иначе говоря, Mystem снимает только частеречную омонимию. Омонимию форм он не снимает.
58 |
59 | ## Как запускать Mystem из питона?
60 |
61 | Для запуска сторонних программ, имеющих интерфейс командной строки, в питоне есть system, предоставляемая модулем os: `os.system("C:\mystem.exe input.txt output.txt")`. Перед добавлением такой конструкции в код, необходимо импортировать модуль os.
62 |
63 | Это нужно, чтобы, например, обработать много файлов циклом:
64 |
65 | ```python
66 | import os
67 | inp = "input_texts"
68 | lst = os.listdir(inp)
69 | for fl in lst:
70 | os.system(r"C:\mystem.exe " + inp + os.sep + fl + " output_texts" + os.sep + fl)
71 | ```
72 |
73 | Этот код берёт из директории *input_texts* все лежащие в ней файлы, отдаёт на разметку майстему и кладёт результат в соседнюю директорию *output_texts*.
74 |
75 | Есть возможность запускать mystem и с помощью специального модуля, **pymystem3** (и некоторых других), который нужно специально установить (его нет в стандартной сборке питона). Исходники pymystem3 и вся документация лежат [вот тут](https://github.com/Digsolab/pymystem3). Это проще и удобнее, потому что с тем, что выдаёт mystem, можно сразу работать как с питоновскими структурами данных. Но медленнее. Иногда гораздо-гораздо медленнее, чем разметить один файл mystem'ом сразу.
76 |
77 | ## Задание
78 |
79 | Скачать mystem и попробовать разные опции его запуска на практике. Посмотреть, чем результат вызова с одними опциями отличается от результата вызова с другими опциями.
80 |
81 |
--------------------------------------------------------------------------------
/Lessons/Морфологический анализ/rus_stopwords.txt:
--------------------------------------------------------------------------------
1 | а
2 | ах
3 | б
4 | без
5 | безо
6 | будем
7 | будет
8 | будете
9 | будешь
10 | буду
11 | будут
12 | будучи
13 | будь
14 | будьте
15 | бы
16 | был
17 | была
18 | были
19 | было
20 | быть
21 | в
22 | вам
23 | вами
24 | вас
25 | ваше
26 | вдруг
27 | ведь
28 | весь
29 | весьма
30 | видеть
31 | видит
32 | вместе
33 | во
34 | вот
35 | все
36 | всего
37 | всей
38 | всем
39 | всеми
40 | всему
41 | всех
42 | всею
43 | всея
44 | вскоре
45 | всю
46 | вся
47 | всё
48 | всём
49 | вы
50 | где
51 | говорил
52 | говорила
53 | говорили
54 | говорит
55 | говорит
56 | говорить
57 | да
58 | даже
59 | делал
60 | делала
61 | делали
62 | делать
63 | для
64 | до
65 | думает
66 | думал
67 | думала
68 | думали
69 | думать
70 | его
71 | едим
72 | едят
73 | ее
74 | ей
75 | ел
76 | ела
77 | ем
78 | ему
79 | емъ
80 | если
81 | ест
82 | есть
83 | ешь
84 | еще
85 | ещё
86 | ею
87 | её
88 | ж
89 | же
90 | за
91 | зачем
92 | здесь
93 | и
94 | из
95 | или
96 | им
97 | ими
98 | имъ
99 | их
100 | к
101 | ка
102 | как
103 | кем
104 | ко
105 | ко
106 | когда
107 | кого
108 | коли
109 | коль
110 | ком
111 | кому
112 | комья
113 | которая
114 | которого
115 | которое
116 | которой
117 | котором
118 | которому
119 | которою
120 | которую
121 | которые
122 | который
123 | которым
124 | которыми
125 | которых
126 | кто
127 | куда
128 | ли
129 | между
130 | меня
131 | мені
132 | мне
133 | мной
134 | мною
135 | мог
136 | моги
137 | могите
138 | могла
139 | могли
140 | могло
141 | могу
142 | могут
143 | мое
144 | моего
145 | моей
146 | моем
147 | моему
148 | моею
149 | можем
150 | может
151 | может
152 | можете
153 | можешь
154 | можно
155 | мои
156 | моим
157 | моими
158 | моих
159 | мой
160 | мочь
161 | мою
162 | моя
163 | моё
164 | моём
165 | мы
166 | на
167 | на
168 | над
169 | надо
170 | наконец
171 | нам
172 | нами
173 | нас
174 | наса
175 | наш
176 | наша
177 | наше
178 | нашего
179 | нашей
180 | нашем
181 | нашему
182 | нашею
183 | наши
184 | нашим
185 | нашими
186 | наших
187 | нашою
188 | нашої
189 | нашу
190 | наші
191 | нашій
192 | нашім
193 | не
194 | него
195 | нее
196 | ней
197 | нем
198 | нему
199 | несколько
200 | нет
201 | нечего
202 | нею
203 | неё
204 | ни
205 | ним
206 | ними
207 | них
208 | ничего
209 | но
210 | ну
211 | нужно
212 | нём
213 | о
214 | об
215 | один
216 | одна
217 | однако
218 | одни
219 | одним
220 | одними
221 | одних
222 | одно
223 | одного
224 | одной
225 | одном
226 | одному
227 | одною
228 | одну
229 | около
230 | он
231 | она
232 | оне
233 | они
234 | оно
235 | опять
236 | от
237 | ответил
238 | ответил
239 | ответила
240 | ответила
241 | ответили
242 | ответили
243 | отвечает
244 | отвечал
245 | отвечала
246 | отвечали
247 | отвечать
248 | ох
249 | очень
250 | перед
251 | перед
252 | по
253 | под
254 | после
255 | потом
256 | почему
257 | при
258 | про
259 | раз
260 | с
261 | сам
262 | сама
263 | сами
264 | самим
265 | самими
266 | самих
267 | само
268 | самого
269 | самом
270 | самому
271 | саму
272 | свое
273 | своего
274 | своей
275 | своем
276 | своему
277 | своею
278 | свои
279 | своим
280 | своими
281 | своих
282 | свой
283 | свою
284 | своя
285 | своё
286 | своём
287 | себе
288 | себя
289 | сказал
290 | сказала
291 | сказали
292 | сказать
293 | скоро
294 | со
295 | собой
296 | собою
297 | спросил
298 | спросила
299 | спросили
300 | стал
301 | стала
302 | стали
303 | та
304 | так
305 | такая
306 | такие
307 | таким
308 | такими
309 | таких
310 | такого
311 | такое
312 | такой
313 | таком
314 | такому
315 | такою
316 | такую
317 | там
318 | те
319 | тебе
320 | тебя
321 | тем
322 | теми
323 | теперь
324 | тех
325 | теє
326 | то
327 | тобой
328 | тобою
329 | тогда
330 | того
331 | той
332 | только
333 | том
334 | томах
335 | тому
336 | тот
337 | тотчас
338 | тою
339 | ту
340 | тут
341 | ты
342 | ті
343 | тією
344 | тієї
345 | тії
346 | у
347 | увидел
348 | увидела
349 | увидели
350 | уж
351 | уже
352 | уже
353 | уже
354 | хотел
355 | хотела
356 | хотели
357 | хотеть
358 | хоть
359 | хотя
360 | хочет
361 | чего
362 | чем
363 | чему
364 | через
365 | что
366 | чтоб
367 | чтобы
368 | чуть
369 | чём
370 | эта
371 | эти
372 | этим
373 | этими
374 | этих
375 | это
376 | этого
377 | этой
378 | этом
379 | этому
380 | этот
381 | этою
382 | эту
383 | я
--------------------------------------------------------------------------------
/Lessons/Структуры данных/KILI_seminar2_datatypes.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ancatmara/learnpython2018/eec59d8a9d05ca80783d39963189cbd80ac661f3/Lessons/Структуры данных/KILI_seminar2_datatypes.pdf
--------------------------------------------------------------------------------
/Lessons/Структуры данных/kilipractice.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # encoding: utf-8
3 |
4 | """
5 | KILI: Programming for Linguists
6 | HSE Linguistics, Fall 2018
7 | Daria Popova
8 |
9 | Practice 2
10 |
11 | Distributed 2018-09-14
12 |
13 | NOTE: Please submit a modified version of this file, including
14 | comments. Python should be able to run through your file without
15 | errors.
16 | """
17 |
18 | import math
19 | import pprint
20 |
21 | """===================================================================
22 | 1 [1 point]
23 |
24 | Complete the function mean for calculating the mean (average) of a
25 | list of numeric values. Your function should take a list vals as its
26 | argument and return a float. Keep in mind that vals might contain int
27 | values.
28 |
29 | Consider doing it with the in-line function sum, which facilitates a fast and readable one-line version of the function.
30 | """
31 |
32 | def mean(vals):
33 | """Return the mean of the values in vals, presupposed to be
34 | numeric (float, int, or long)."""
35 |
36 | """===================================================================
37 | 2 [1 point]
38 |
39 | Complete the function sd for calculating the standard deviation of a
40 | list of numeric values. Your function should take a list vals as its
41 | value and return a float. Keep in mind that vals might contain int
42 | values.
43 |
44 | For details on calculating the standard deviation, see
45 | http://en.wikipedia.org/wiki/Standard_deviation
46 |
47 | I suggest using float(len(vals)-1) for the denominator, but
48 | float(len(vals)) is fine.
49 |
50 | To get the square root of a float x, using math.sqrt(x)
51 | """
52 |
53 | def sd(vals):
54 | """Return the standard deviation of the values in vals,
55 | presupposed to be numeric (float, int, or long)."""
56 |
57 | """===================================================================
58 | 3 [1 point]
59 |
60 | Complete the function zscore for computing the z-score (normal score)
61 | of a list of numeric values. Your function should take a list vals as
62 | its value and return a list of z-score normed values. Use mean and sd,
63 | as defined above, for this calculation.
64 |
65 | For details on calculating the z-score, see
66 | http://en.wikipedia.org/wiki/Z_score
67 | """
68 |
69 | """def zscore(vals):
70 | This function is radical: it will replace vals with zscored vals.
71 | m = mean(vals)
72 | s = sd(vals)
73 | if sd(vals) > 0:
74 | for x in range(0,len(vals)):
75 | vals[x] = (vals[x] - m) / s
76 | return vals
77 | else:
78 | return 'n/a'"""
79 |
80 | def zscore(vals):
81 | """Return the z-scored version of vals."""
82 |
83 | """===================================================================
84 | 4
85 |
86 | Intro to comma-separated values. The string myspreadsheet stores 11
87 | lines of comma-separated values, with the first line giving the column
88 | names and the other lines giving the data on 10 imaginary subjects.
89 | Below are some questions that ask you to write functions for working
90 | with this data.
91 | """
92 |
93 | myspreadsheet ="""Subject,Height,Occupation
94 | 1,74.37000326528938,Psychologist
95 | 2,67.49686206937491,Psychologist
96 | 3,74.92356434760966,Psychologist
97 | 4,64.62372198999978,Psychologist
98 | 5,67.76787900026083,Linguist
99 | 6,61.50397707923559,Psychologist
100 | 7,62.73680961908566,Psychologist
101 | 8,68.60803984763902,Linguist
102 | 9,70.16090500135535,Psychologist
103 | 10,76.81144438287173,Linguist"""
104 |
105 | """--------------------------------------------------
106 | Random facts: The column of heights, presumably in
107 | inches, was generated with
108 |
109 | import random
110 |
111 | and then repeated runs of
112 |
113 | random.uniform(60,77)
114 |
115 | The column of occupations was generated with
116 |
117 | d = {0:'Psychologist',1:'Linguist'}
118 |
119 | and then repeated runs of
120 |
121 | d[random.randint(0,1)]
122 | --------------------------------------------------"""
123 |
124 | """===================================================================
125 | 4.1 [3 points]
126 |
127 | Basic CSV parser. Complete the following function for turning the str
128 | myspreadsheet into a 10x3 matrix of data. I should emphasize that the
129 | top line of myspreadsheet is not part of the data. It's just there to
130 | help us out.
131 |
132 | Column 0 of your data should be int values.
133 |
134 | Column 1 of your data should be float values.
135 |
136 | To test your parser, call csv_parser_test, which will work with
137 | no modifications.
138 | """
139 |
140 | def csv_parser(s):
141 | """Parses the string s into lines, and then parses those lines by
142 | splitting on the comma and converting the numerical data to int.
143 | The output is a list of lists of subject data."""
144 |
145 | # Data is our output. It will be a list of lists.
146 |
147 | # Split csv into lines and store them in a list called 'lines'.
148 |
149 | # Remove the first element from lines, so that you have only the data lines left.
150 |
151 | # At this stage, we loop through the list called lines.
152 | # As you loop
153 | # i. split each line on the commas;
154 | # ii. convert the Subject variable to int.
155 | # iii. convert the Height variable to float.
156 | # iv. add to data a list consisting of this line's Subject, Height, and Occupation values
157 |
158 | def csv_parser_test():
159 | """Display the output of csv_parser(myspreadsheet) and
160 | test it a little bit."""
161 | data = csv_parser(myspreadsheet)
162 | print 'Your data object:'
163 | pp = pprint.PrettyPrinter(indent=4)
164 | pp.pprint(data)
165 | # Did your parser work?
166 | for row_num, row in enumerate(data):
167 | try:
168 | assert len(row) == 3
169 | except AssertionError:
170 | print "Row %s seems to be misparsed; its length is %s" % (row_num, len(row))
171 | # Check on one of the values:
172 | try:
173 | assert data[4][2] == 'Linguist'
174 | except AssertionError:
175 | print "Error: data[4][2] should equal 'Linguist'; actual value is %s" % data[4][2]
176 | # Did you remember your int conversions?
177 | try:
178 | assert isinstance(data[0][0], int)
179 | except AssertionError:
180 | print "Error: data[0][0] should be an int"
181 | # Did you remember your float conversions?
182 | try:
183 | assert isinstance(data[6][1], float)
184 | except AssertionError:
185 | print "Error: data[6][1] should be a float"
186 |
187 | """===================================================================
188 | 4.2 [1 point]
189 |
190 | Complete the following function for computing the mean height of the
191 | subjects in this data set, using your mean function from above.
192 | """
193 |
194 | def mean_height(data):
195 | """Return the mean numerical value of column 1 in an list of lists.
196 | data is the output of csv_parser(myspreadsheet)"""
197 |
198 | """===================================================================
199 | 4.3 [2 points]
200 |
201 | Occupation distribution. Complete the following function so that it
202 | returns a dictionary mapping occupation names into the number of times
203 | they occur in the data.
204 | """
205 |
206 | def occupation_distribution(data):
207 | """Returns the list of occupations given in column 2 of data.
208 | data is the output of csv_parser(myspreadsheet)"""
209 |
210 | """==================================================================="""
211 |
212 | def proper_title_case(s):
213 | """
214 | Try to do a better job of getting title case. For example,
215 | "the cat in the hat".title() ==> "The Cat In The Hat",
216 | but we want "The Cat in the Hat"
217 | """
218 | nocaps = ["the"] # This needs to be extended.
219 |
220 | """===================================================================
221 |
222 | 5. Fillers, making nonsense items [1 point]
223 |
224 | 5.1
225 | A frequent task for psycholinguists is finding items for experiments, either items that directly exemplify some property we want to test or items that fill out an experiment and can be used to distract subjects from the true goal of the experiment.
226 | Imagine what we want are CV monosyllables. We could just try to think of all possible monosyllables with a CV shape, but another way to go is to generate these programmatically. If we know what the possible consonants are and what the possible vowels are, we can generate a list of possible CV monosyllables quite simply.
227 |
228 | """
229 | #define vowels and consonants
230 | #for every vowel
231 | #choose a consonant
232 | #now print them together
233 | """=====
234 | 5.2
235 | The same kind of logic can be used to construct nonsense sentences. Imagine we want every possible SVO sentence in some (nonsense) language. We have a set of
236 | nouns and transitive verbs. We can combine them straightforwardly.
237 | """
238 |
239 | #define nouns and verbs
240 | #combine them
241 |
242 | ######################################################################
243 |
244 | if __name__ == '__main__':
245 |
246 | #print proper_title_case("the cat in the hat")
247 | #print proper_title_case("an ant on a table")
248 | #print mean([1,2,3,4,5,6,7,8,9,10])
249 | #print sd([0,1,2])
250 | #print zscore([0,2,4])
251 | #print csv_parser_test()
252 | #print mean_height(myspreadsheet)
253 | #print occupation_distribution(myspreadsheet)
254 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python for Linguists 2018
2 |
3 | Семинары по программированию на Python для 2 курса Школы Лингвистики НИУ ВШЭ, 2018-2019 гг.
4 |
5 | ### Преподаватели
6 | * Оксана Владимировна Дереза ([почта](mailto:oksana.dereza@gmail.com), [telegram](https://t.me/ancatmara))
7 | * Дарья Павловна Попова ([почта](mailto:daschapopowa@gmail.com))
8 | * Ростислав Алексеевич Бородин ([почта](mailto:roctbb@gmail.com), [telegram](https://t.me/roctbb))
9 |
10 | ### Ассистенты
11 | * Валерия Алексеевна Морозова ([почта](mailto:tito_alba@mail.ru), [telegram](https://t.me/eternal_phobia))
12 |
13 | ### Информация
14 | * Вот [эту форму](https://goo.gl/forms/WAVZWtjpyoRDcgm22) нужно обязательно заполнить, иначе мы не сможем проверять ваши домашки. :)
15 | * А [это](https://docs.google.com/spreadsheets/d/1MRWqsqtRnsgMb5c2ywL1LKUlDvpD8G0EzG05cPQ7jc4/edit?usp=sharing) ведомости по курсу.
16 |
17 | ### Telegram
18 | * [Чат 2-ой группы](https://t.me/joinchat/ADMP3VFYTP7EoizUYT2frg)
19 | * [Чат 4-ой группы](https://t.me/joinchat/BSwQA0nY3ueMOZ8gFhe-kQ)
20 |
21 |
22 | ### План курса: 1-2 модуль
23 |