[Python, Учебный процесс в IT] Повелевать Web’ом с помощью Python (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Путешествие в простую веб-автоматизацию
Проблема: Отправка домашних заданий требует навигации по лабиринту веб-страниц, настолько сложной, что несколько раз я отправлял задание в неправильное место. Кроме того, хоть и этот процесс занимает всего 1–2 минуты, иногда он кажется непреодолимым препятствием (например, когда я закончил задание слишком поздно ночью и едва могу вспомнить свой пароль).
Решение: Используйте Python для автоматической отправки выполненных заданий! В идеале я мог бы сохранить задание, набрать несколько клавиш и загрузить свою работу за считанные секунды. Сначала это звучало слишком хорошо, чтобы быть правдой, но потом я обнаружил Selenium, инструмент, который можно использовать с Python для навигации по сети.
Каждый раз, когда мы повторяем утомительные действия в Интернете с одинаковой последовательностью шагов, это отличный шанс написать программу для автоматизации процесса. С Selenium и Python нам просто нужно написать сценарий один раз, и затем мы сможем запустить его сколько угодно раз и уберечь себя от повторения однообразных задач (и в моем случае исключается возможность отправки задания в неправильное место)!
Здесь я рассмотрю решение, разработанное мной для автоматической (и правильной) отправки моих заданий. Попутно мы рассмотрим основы использования Python и selenium для программного управления вебом. Хотя эта программа работает (я использую ее каждый день!), она довольно индивидуальна, поэтому вы не сможете скопировать и вставить код для своего приложения. Тем не менее, общие методы здесь могут быть применены к неограниченному числу ситуаций. (Если вы хотите увидеть полный код, он доступен на GitHub).
Подход
Прежде чем мы перейдем к интересной части автоматизации, нам необходимо выяснить общую структуру нашего решения. Начинать программировать без плана — отличный способ потратить много часов и разочароваться. Я хочу написать программу для отправки выполненных заданий по классу в правильное место в Canvas’e («система управления обучением» моего университета). Начнем сначала, мне нужен способ сообщить программе название задания для отправки и класс. Я использовал простой подход и создал папку для хранения выполненных заданий с дочерними папками для каждого класса. В дочерние папки я помещаю готовый документ, названный для конкретного задания. Программа может выяснить имя класса по папке и название задания по названию документа.
Вот пример, где название класса — EECS491, а задание — Задание 3 — Вывод в больших графических моделях».
File structure (слева) и Complete Assignment (справа).
Первая часть программы представляет собой цикл, который проходит по папкам, чтобы найти задание и класс, которые мы храним в кортеже Python:
# os for file management
import os
# Build tuple of (class, file) to turn in
submission_dir = 'completed_assignments'
dir_list = list(os.listdir(submission_dir))
for directory in dir_list:
file_list = list(os.listdir(os.path.join(submission_dir,
directory)))
if len(file_list) != 0:
file_tup = (directory, file_list[0])
print(file_tup)
('EECS491', 'Assignment 3 — Inference in Larger Graphical Models.txt')
Это заботится об управлении файлами, и теперь программа знает класс и задание для включения. Следующим шагом является использование Selenium для перехода на правильную веб-страницу и загрузки задания.
Веб-контроль с Selenium
Чтобы начать работу с Selenium, мы импортируем библиотеку и создаем веб-драйвер, который является браузером, управляемым нашей программой. В этом случае я буду использовать Chrome в качестве браузера и отправлять драйвер на веб-сайт Canvas, где я отправляю задания.
import selenium
# Using Chrome to access web
driver = webdriver.Chrome()
# Open the website
driver.get('https://canvas.case.edu')
Когда мы открываем веб-страницу Canvas, нас встречает первое препятствие — поле для входа! Чтобы обойти это, нам нужно будет ввести идентификатор и пароль и нажать кнопку входа.
Представьте, что веб-драйвер — это человек, который никогда раньше не видел веб-страницу: нам нужно точно сказать, куда нажимать, что печатать и какие кнопки нажимать. Есть несколько способов сообщить нашему веб-драйверу, какие элементы найти, и все они используют селекторы. Селектор — это уникальный идентификатор элемента на веб-странице. Чтобы найти селектор для определенного элемента, скажем, поле “CWRU ID”, нам нужно посмотреть код веб-страницы. В Chrome это можно сделать, нажав «Ctrl + Shift + I» или щелкнув правой кнопкой мыши на любом элементе и выбрав “Посмотреть код”. Это открывает инструменты разработчика Chrome, чрезвычайно полезное приложение, которое показывает HTML, лежащий в основе любой веб-страницы.
Чтобы найти селектор для поля «CWRU ID», я щелкнул правой кнопкой мыши в поле, нажал «Посмотреть код» и увидел следующее в инструментах разработчика. Выделенная строка соответствует элементу id_box (эта строка называется тегом HTML).
Этот HTML может выглядеть подавляющим, но мы можем игнорировать большую часть информации и сосредоточиться на частях id = "username" и name = "username". (они известны как атрибуты тега HTML).
Чтобы выбрать поле id с помощью нашего веб-драйвера, мы можем использовать атрибут id или name, который мы нашли в инструментах разработчика. Веб-драйверы в Selenium имеют много разных способов выбора элементов на веб-странице, и часто есть несколько способов выбрать один и тот же элемент:
# Select the id box
id_box = driver.find_element_by_name('username')
# Equivalent Outcome!
id_box = driver.find_element_by_id('username')
Наша программа теперь имеет доступ к id_box, и мы можем взаимодействовать с ним различными способами, такими как ввод ключей или нажатие (если мы выбрали кнопку).
# Send id information
id_box.send_keys('my_username')
Мы выполняем один и тот же процесс для поля ввода пароля и кнопки входа, выбирая каждый из них в зависимости от того, что мы видим в инструментах разработчика Chrome. Затем мы отправляем информацию элементам или нажимаем на них по мере необходимости.
# Find password box
pass_box = driver.find_element_by_name('password')
# Send password
pass_box.send_keys('my_password')
# Find login button
login_button = driver.find_element_by_name('submit')
# Click login
login_button.click()
Как только мы вошли в систему, нас приветствует эта слегка пугающая панель инструментов:
Нам снова нужно провести программу через веб-страницу, указав именно те элементы, на которые нужно нажать, и информацию, которую нужно ввести. В этом случае я говорю программе выбрать курсы из меню слева, а затем класс, соответствующий заданию, которое мне нужно сдать:
# Find and click on list of courses
courses_button = driver.find_element_by_id('global_nav_courses_link')
courses_button.click()
# Get the name of the folder
folder = file_tup[0]
# Class to select depends on folder
if folder == 'EECS491':
class_select = driver.find_element_by_link_text('Artificial Intelligence: Probabilistic Graphical Models (100/10039)')
elif folder == 'EECS531':
class_select = driver.find_element_by_link_text('Computer Vision (100/10040)')
# Click on the specific class
class_select.click()
Программа находит правильный класс, используя имя папки, которую мы сохранили на первом шаге. В этом случае я использую метод выбора find_element_by_link_text, чтобы найти определенный класс. «Текст ссылки» для элемента — это просто еще один селектор, который мы можем найти, просмотрев страницу:
Этот рабочий процесс может показаться немного утомительным, но помните, что мы должны сделать это только один раз, когда пишем нашу программу! После этого мы можем нажать «Выполнить» столько раз, сколько захотим, и программа зайдет за нас на все эти страницы.
Мы используем один и тот же процесс проверки страницы — выбора элемента — взаимодействия с элементом, чтобы пройти еще пару экранов. Наконец, мы достигаем страницы отправки задания:
В этот момент я мог видеть финишную черту, но изначально этот экран меня озадачил. Я мог бы довольно легко нажать на поле «Выбрать файл», но как я должен был выбрать нужный файл для загрузки? Ответ оказывается невероятно простым! Мы находим поле Choose File с помощью селектора и используем метод send_keys для передачи точного пути к файлу (называемого file_location в приведенном ниже коде) к блоку:
# Choose File button
choose_file = driver.find_element_by_name('attachments[0][uploaded_data]')
# Complete path of the file
file_location = os.path.join(submission_dir, folder, file_name)
# Send the file location to the button
choose_file.send_keys(file_location)
Отправляя точный путь файла, мы можем пропустить весь процесс навигации по папкам, чтобы найти нужный файл. После отправки пути мы получаем следующий экран, показывающий, что наш файл загружен и готов к отправке.
Теперь мы выбираем кнопку “Отправить задание”, нажимаем, и наше задание отправлено!
# Locate submit button and click
submit_assignment = driver.find_element_by_id('submit_file_button')
submit_assignent.click()
Уборка
Управление файлами — это всегда критический шаг, и я хочу быть уверенным, что не отправлю повторно или не потеряю старые задания. Я решил, что лучшим решением будет сохранить файл, который будет помещен в папку completed_assignments, и переместить файлы в папку submitted_assignments, как только они будут загружены. Последний бит кода использует модуль os для перемещения завершенного задания в нужное место.
# Location of files after submission
submitted_file_location = os.path.join(submitted_dir, submitted_file_name)
# Rename essentially copies and pastes files
os.rename(file_location, submitted_file_location)
Весь исходный код упакован в один скрипт, который я могу запустить из командной строки. Чтобы ограничить возможность ошибок, я отправляю только одно задание за раз, что не составляет большого труда, учитывая, что запуск программы занимает всего около 5 секунд!
Вот как это выглядит, когда я запускаю программу:
Программа дает мне возможность убедиться, что это правильное задание перед загрузкой. После завершения программы я получаю следующий вывод:
Пока программа работает, я могу наблюдать, как Python работает на меня:
Выводы
Техника автоматизации с помощью Python отлично подходит для многих задач, как общих, так и в моей области науки о данных. Например, мы могли бы использовать Selenium для автоматической загрузки новых файлов данных каждый день (при условии, что у веб-сайта нет API). Хотя на первый взгляд создание сценария может показаться трудоемким, преимущество заключается в том, что мы можем заставить компьютер повторять эту последовательность столько раз, сколько захотим, точно таким же образом. Программа никогда не потеряет фокус и зайдет в Twitter. Она будет точно выполнять шаги с идеальной последовательностью (алгоритм будет прекрасно работать, пока сайт не изменится).
Я должен упомянуть, что вы должны быть осторожными, прежде чем автоматизировать критические задачи. Этот пример является относительно низким риском, так как я всегда могу вернуться и повторно отправить задания, и я обычно перепроверяю работу программы. Веб-сайты меняются, и если вы не измените программу в ответ, вы можете получить скрипт, который делает что-то совершенно иное, чем вы изначально предполагали!
В плане окупаемости эта программа экономит мне около 30 секунд на каждое задание, а на ее написание уходит 2 часа. Так что, если я использую ее для сдачи 240 заданий, я выйду в плюс по времени! Тем не менее, отдача от этой программы заключается в разработке классного решения проблемы и многому учит в процессе. Хотя мое время могло бы быть более эффективно потрачено на выполнение заданий, а не на выяснение того, как автоматически сдавать их, я полностью наслаждался этой задачей.Есть несколько вещей, приносящих такое удовлетворение, как решение проблем, и Python оказывается довольно хорошим инструментом для этого.
Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:
- Курс по Machine Learning (12 недель)
- Обучение профессии Data Science с нуля (12 месяцев)
- Профессия аналитика с любым стартовым уровнем (9 месяцев)
- Курс «Python для веб-разработки» (9 месяцев)
Читать еще
- Тренды в Data Scienсe 2020
- Data Science умерла. Да здравствует Business Science
- Крутые Data Scientist не тратят время на статистику
- Как стать Data Scientist без онлайн-курсов
- Шпаргалка по сортировке для Data Science
- Data Science для гуманитариев: что такое «data»
- Data Scienсe на стероидах: знакомство с Decision Intelligence
===========
Источник:
habr.com
===========
===========
Автор оригинала: Will Koehrsen
===========Похожие новости:
- [Визуализация данных, Интерфейсы, Машинное обучение, Учебный процесс в IT] ML+HCI: что исследуют на стыке машинного обучения и человеко-компьютерного взаимодействия
- [Data Mining, Визуализация данных, Natural Language Processing, Программирование, Python] How to find an English teacher. Part 1
- [Машинное обучение, MySQL, Python] Web-сервер машинного обучения «ВКФ-решатель»
- [Python, Программирование] Введение в асинхронное программирование на Python (перевод)
- [Python, Программирование] А вы можете решить эти три (обманчиво) простые задачи на Python? (перевод)
- [DevOps, Python, Машинное обучение, Управление разработкой] MLOps — Cook book, chapter 1
- [Python, Микросервисы, Программирование, Тестирование веб-сервисов] Функциональные тесты в Циан
- [Open source, Python] Ищем фильмы, книги и подкасты с помощью Python
- [Microsoft Azure, Облачные сервисы, Сетевые технологии, Учебный процесс в IT] Как IT гиганты помогают образованию? Часть 2: Microsoft
- [Научно-популярное, Учебный процесс в IT] Датасет — это просто тест Роршаха (вы видите то, что хотите увидеть) (перевод)
Теги для поиска: #_python, #_uchebnyj_protsess_v_it (Учебный процесс в IT), #_uchebnyj_protsess (учебный процесс), #_blog_kompanii_skillfactory (
Блог компании SkillFactory
), #_python, #_uchebnyj_protsess_v_it (
Учебный процесс в IT
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 21-Ноя 22:25
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Путешествие в простую веб-автоматизацию Проблема: Отправка домашних заданий требует навигации по лабиринту веб-страниц, настолько сложной, что несколько раз я отправлял задание в неправильное место. Кроме того, хоть и этот процесс занимает всего 1–2 минуты, иногда он кажется непреодолимым препятствием (например, когда я закончил задание слишком поздно ночью и едва могу вспомнить свой пароль). Решение: Используйте Python для автоматической отправки выполненных заданий! В идеале я мог бы сохранить задание, набрать несколько клавиш и загрузить свою работу за считанные секунды. Сначала это звучало слишком хорошо, чтобы быть правдой, но потом я обнаружил Selenium, инструмент, который можно использовать с Python для навигации по сети. Каждый раз, когда мы повторяем утомительные действия в Интернете с одинаковой последовательностью шагов, это отличный шанс написать программу для автоматизации процесса. С Selenium и Python нам просто нужно написать сценарий один раз, и затем мы сможем запустить его сколько угодно раз и уберечь себя от повторения однообразных задач (и в моем случае исключается возможность отправки задания в неправильное место)! Здесь я рассмотрю решение, разработанное мной для автоматической (и правильной) отправки моих заданий. Попутно мы рассмотрим основы использования Python и selenium для программного управления вебом. Хотя эта программа работает (я использую ее каждый день!), она довольно индивидуальна, поэтому вы не сможете скопировать и вставить код для своего приложения. Тем не менее, общие методы здесь могут быть применены к неограниченному числу ситуаций. (Если вы хотите увидеть полный код, он доступен на GitHub). Подход Прежде чем мы перейдем к интересной части автоматизации, нам необходимо выяснить общую структуру нашего решения. Начинать программировать без плана — отличный способ потратить много часов и разочароваться. Я хочу написать программу для отправки выполненных заданий по классу в правильное место в Canvas’e («система управления обучением» моего университета). Начнем сначала, мне нужен способ сообщить программе название задания для отправки и класс. Я использовал простой подход и создал папку для хранения выполненных заданий с дочерними папками для каждого класса. В дочерние папки я помещаю готовый документ, названный для конкретного задания. Программа может выяснить имя класса по папке и название задания по названию документа. Вот пример, где название класса — EECS491, а задание — Задание 3 — Вывод в больших графических моделях». File structure (слева) и Complete Assignment (справа). Первая часть программы представляет собой цикл, который проходит по папкам, чтобы найти задание и класс, которые мы храним в кортеже Python: # os for file management
import os # Build tuple of (class, file) to turn in submission_dir = 'completed_assignments' dir_list = list(os.listdir(submission_dir)) for directory in dir_list: file_list = list(os.listdir(os.path.join(submission_dir, directory))) if len(file_list) != 0: file_tup = (directory, file_list[0]) print(file_tup) ('EECS491', 'Assignment 3 — Inference in Larger Graphical Models.txt') Это заботится об управлении файлами, и теперь программа знает класс и задание для включения. Следующим шагом является использование Selenium для перехода на правильную веб-страницу и загрузки задания. Веб-контроль с Selenium Чтобы начать работу с Selenium, мы импортируем библиотеку и создаем веб-драйвер, который является браузером, управляемым нашей программой. В этом случае я буду использовать Chrome в качестве браузера и отправлять драйвер на веб-сайт Canvas, где я отправляю задания. import selenium
# Using Chrome to access web driver = webdriver.Chrome() # Open the website driver.get('https://canvas.case.edu') Когда мы открываем веб-страницу Canvas, нас встречает первое препятствие — поле для входа! Чтобы обойти это, нам нужно будет ввести идентификатор и пароль и нажать кнопку входа. Представьте, что веб-драйвер — это человек, который никогда раньше не видел веб-страницу: нам нужно точно сказать, куда нажимать, что печатать и какие кнопки нажимать. Есть несколько способов сообщить нашему веб-драйверу, какие элементы найти, и все они используют селекторы. Селектор — это уникальный идентификатор элемента на веб-странице. Чтобы найти селектор для определенного элемента, скажем, поле “CWRU ID”, нам нужно посмотреть код веб-страницы. В Chrome это можно сделать, нажав «Ctrl + Shift + I» или щелкнув правой кнопкой мыши на любом элементе и выбрав “Посмотреть код”. Это открывает инструменты разработчика Chrome, чрезвычайно полезное приложение, которое показывает HTML, лежащий в основе любой веб-страницы. Чтобы найти селектор для поля «CWRU ID», я щелкнул правой кнопкой мыши в поле, нажал «Посмотреть код» и увидел следующее в инструментах разработчика. Выделенная строка соответствует элементу id_box (эта строка называется тегом HTML). Этот HTML может выглядеть подавляющим, но мы можем игнорировать большую часть информации и сосредоточиться на частях id = "username" и name = "username". (они известны как атрибуты тега HTML). Чтобы выбрать поле id с помощью нашего веб-драйвера, мы можем использовать атрибут id или name, который мы нашли в инструментах разработчика. Веб-драйверы в Selenium имеют много разных способов выбора элементов на веб-странице, и часто есть несколько способов выбрать один и тот же элемент: # Select the id box
id_box = driver.find_element_by_name('username') # Equivalent Outcome! id_box = driver.find_element_by_id('username') Наша программа теперь имеет доступ к id_box, и мы можем взаимодействовать с ним различными способами, такими как ввод ключей или нажатие (если мы выбрали кнопку). # Send id information
id_box.send_keys('my_username') Мы выполняем один и тот же процесс для поля ввода пароля и кнопки входа, выбирая каждый из них в зависимости от того, что мы видим в инструментах разработчика Chrome. Затем мы отправляем информацию элементам или нажимаем на них по мере необходимости. # Find password box
pass_box = driver.find_element_by_name('password') # Send password pass_box.send_keys('my_password') # Find login button login_button = driver.find_element_by_name('submit') # Click login login_button.click() Как только мы вошли в систему, нас приветствует эта слегка пугающая панель инструментов: Нам снова нужно провести программу через веб-страницу, указав именно те элементы, на которые нужно нажать, и информацию, которую нужно ввести. В этом случае я говорю программе выбрать курсы из меню слева, а затем класс, соответствующий заданию, которое мне нужно сдать: # Find and click on list of courses
courses_button = driver.find_element_by_id('global_nav_courses_link') courses_button.click() # Get the name of the folder folder = file_tup[0] # Class to select depends on folder if folder == 'EECS491': class_select = driver.find_element_by_link_text('Artificial Intelligence: Probabilistic Graphical Models (100/10039)') elif folder == 'EECS531': class_select = driver.find_element_by_link_text('Computer Vision (100/10040)') # Click on the specific class class_select.click() Программа находит правильный класс, используя имя папки, которую мы сохранили на первом шаге. В этом случае я использую метод выбора find_element_by_link_text, чтобы найти определенный класс. «Текст ссылки» для элемента — это просто еще один селектор, который мы можем найти, просмотрев страницу: Этот рабочий процесс может показаться немного утомительным, но помните, что мы должны сделать это только один раз, когда пишем нашу программу! После этого мы можем нажать «Выполнить» столько раз, сколько захотим, и программа зайдет за нас на все эти страницы. Мы используем один и тот же процесс проверки страницы — выбора элемента — взаимодействия с элементом, чтобы пройти еще пару экранов. Наконец, мы достигаем страницы отправки задания: В этот момент я мог видеть финишную черту, но изначально этот экран меня озадачил. Я мог бы довольно легко нажать на поле «Выбрать файл», но как я должен был выбрать нужный файл для загрузки? Ответ оказывается невероятно простым! Мы находим поле Choose File с помощью селектора и используем метод send_keys для передачи точного пути к файлу (называемого file_location в приведенном ниже коде) к блоку: # Choose File button
choose_file = driver.find_element_by_name('attachments[0][uploaded_data]') # Complete path of the file file_location = os.path.join(submission_dir, folder, file_name) # Send the file location to the button choose_file.send_keys(file_location) Отправляя точный путь файла, мы можем пропустить весь процесс навигации по папкам, чтобы найти нужный файл. После отправки пути мы получаем следующий экран, показывающий, что наш файл загружен и готов к отправке. Теперь мы выбираем кнопку “Отправить задание”, нажимаем, и наше задание отправлено! # Locate submit button and click
submit_assignment = driver.find_element_by_id('submit_file_button') submit_assignent.click() Уборка Управление файлами — это всегда критический шаг, и я хочу быть уверенным, что не отправлю повторно или не потеряю старые задания. Я решил, что лучшим решением будет сохранить файл, который будет помещен в папку completed_assignments, и переместить файлы в папку submitted_assignments, как только они будут загружены. Последний бит кода использует модуль os для перемещения завершенного задания в нужное место. # Location of files after submission
submitted_file_location = os.path.join(submitted_dir, submitted_file_name) # Rename essentially copies and pastes files os.rename(file_location, submitted_file_location) Весь исходный код упакован в один скрипт, который я могу запустить из командной строки. Чтобы ограничить возможность ошибок, я отправляю только одно задание за раз, что не составляет большого труда, учитывая, что запуск программы занимает всего около 5 секунд! Вот как это выглядит, когда я запускаю программу: Программа дает мне возможность убедиться, что это правильное задание перед загрузкой. После завершения программы я получаю следующий вывод: Пока программа работает, я могу наблюдать, как Python работает на меня: Выводы Техника автоматизации с помощью Python отлично подходит для многих задач, как общих, так и в моей области науки о данных. Например, мы могли бы использовать Selenium для автоматической загрузки новых файлов данных каждый день (при условии, что у веб-сайта нет API). Хотя на первый взгляд создание сценария может показаться трудоемким, преимущество заключается в том, что мы можем заставить компьютер повторять эту последовательность столько раз, сколько захотим, точно таким же образом. Программа никогда не потеряет фокус и зайдет в Twitter. Она будет точно выполнять шаги с идеальной последовательностью (алгоритм будет прекрасно работать, пока сайт не изменится). Я должен упомянуть, что вы должны быть осторожными, прежде чем автоматизировать критические задачи. Этот пример является относительно низким риском, так как я всегда могу вернуться и повторно отправить задания, и я обычно перепроверяю работу программы. Веб-сайты меняются, и если вы не измените программу в ответ, вы можете получить скрипт, который делает что-то совершенно иное, чем вы изначально предполагали! В плане окупаемости эта программа экономит мне около 30 секунд на каждое задание, а на ее написание уходит 2 часа. Так что, если я использую ее для сдачи 240 заданий, я выйду в плюс по времени! Тем не менее, отдача от этой программы заключается в разработке классного решения проблемы и многому учит в процессе. Хотя мое время могло бы быть более эффективно потрачено на выполнение заданий, а не на выяснение того, как автоматически сдавать их, я полностью наслаждался этой задачей.Есть несколько вещей, приносящих такое удовлетворение, как решение проблем, и Python оказывается довольно хорошим инструментом для этого. Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:
Читать еще
=========== Источник: habr.com =========== =========== Автор оригинала: Will Koehrsen ===========Похожие новости:
Блог компании SkillFactory ), #_python, #_uchebnyj_protsess_v_it ( Учебный процесс в IT ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 21-Ноя 22:25
Часовой пояс: UTC + 5