Статьи

Как я научился перестать беспокоиться и любить инструмент капитализации

Я пишу много уроков для Envato Tuts +. Эти учебники имеют заголовки, которые должны следовать определенным правилам использования заглавных букв. Tuts + предоставляет нам, авторам, веб-инструмент, который берет текст заголовка и возвращает заголовок с правильной заглавной буквы. Когда я пишу свои учебные пособия, я пытаюсь войти в поток, и переключение на инструмент капитализации нарушает мой поток. Раньше я просто делал это и делал капитализацию сам.

Оказывается, я часто допускал ошибки, что вызывало дополнительную работу у редакторов Tuts +, которые должны были их исправить. Будучи программистом, я решил запрограммировать выход из проблемы. Я все еще пишу свои собственные заголовки, но когда я закончу, я запускаю небольшую программу на Python, которая анализирует мою статью, обнаруживает все заголовки, а затем запускает их с помощью инструмента капитализации Tuts + и правильно прописывает все заголовки.

Поскольку инструмент капитализации является веб-приложением, а не API, мне пришлось автоматизировать браузер, чтобы вызвать его и извлечь заглавные буквы. В этом уроке вы узнаете, как управлять браузером в Python с помощью Selenium и заставить его выполнять ваши ставки.

Заглавные буквы — это не ракетостроение, но и не тривиальное. Есть несколько стилей, с некоторым перекрытием и некоторыми вариациями. Это более или менее консенсус:

  • Прописать все слова четырьмя или более буквами.
  • Всегда пишите заглавными буквами первые и последние слова.
  • Не используйте заглавные буквы: a, an, the.
  • Не используйте короткие сочетания с заглавными буквами: и, или, ни, для, но, так, пока.

Тогда есть множество исключений и особых ситуаций (например, заголовок переходит на следующую строку). Но это все спорно. Даже если я решил написать свой собственный код с заглавной буквы, Tuts + уже выбрал их вкус, и мне нужно соответствовать их выбранному стилю.

Инструмент капитализации Tuts + является внутренним инструментом, предназначенным для использования только инструкторами Tuts +, поэтому я не могу использовать его в качестве демонстрации. Тем не менее, я нашел похожий инструмент под названием Title Case Converter . Это веб-приложение с большой текстовой областью, в которой вы можете ввести свой заголовок (или заголовок), кнопку преобразования, которую вы нажимаете, чтобы отправить форму, область вывода, которая отображается с правильно прописным заголовком, и, наконец, кнопка копирования, которая копирует преобразованный заголовок в буфер обмена.

Онлайн конвертер дел

OK. Я собираюсь использовать онлайн конвертер дел, но нет API. Это не большая проблема. Я могу автоматизировать браузер и смоделировать пользователя, который вводит заголовок в поле ввода, нажимает кнопку конвертирования, ждет появления вывода, нажимает кнопку копирования и, наконец, вставляет заголовок с правильной прописной буквой из буфера обмена.

Первый шаг — выбрать браузер для автоматизации. Я выбрал Selenium WebDriver, который раньше успешно использовал. Остальная часть плана:

  • Запустите браузер.
  • Перейдите к URL-адресу онлайн-конвертера дел.
  • Найдите все необходимые элементы.
  • Заполните поле ввода.
  • Отправьте форму.
  • Ждите выхода.
  • Нажмите кнопку копирования.
  • Прочитайте заглавную букву из буфера обмена.

Полный исходный код можно найти на GitLab .

Selenium автоматизирует браузеры с 2004 года. В 2008 году он объединился с проектом WebDriver, в котором рассматриваются некоторые ограничения исходного Selenium (например, работа в песочнице JavaScript).

Selenium по-прежнему предлагает оригинальный аромат Selenium под названием Selenium RC (Remote Control). Он также имеет IDE для написания автоматизированных наборов тестов и инструмент под названием Selenium Grid, который масштабирует Selenium RC для больших наборов тестов, которые должны работать в нескольких средах. Мы ограничимся программным доступом к браузеру через API WebDriver (он же Selenium 2).

Установка Selenium так же проста, как и pipenv selenium . Если вы не знакомы с Pipenv, ознакомьтесь с « Пересмотром упаковки Python с помощью Pipenv» . Вам также нужен определенный веб-драйвер. Есть веб-драйверы для разных браузеров и серверных частей. Вы можете найти полный список на сайте Selenium .

Я выбрал веб-драйвер Chrome для этого урока. Вот последняя версия .

Это один zip-файл, который содержит один исполняемый файл (есть версии для Windows, macOS и Linux). После того, как вы загрузили его, распакуйте его и пройдите по пути.

Поздравляем! Теперь вы готовы использовать Selenium WebDriver из Python.

Selenium позволяет легко запускать браузер. Если у вас есть правильный веб-драйвер на вашем пути, вы просто импортируете модуль selenium.webdriver и вызываете правильный метод для запуска вашего браузера:

1
2
3
from selenium import webdriver
 
driver = webdriver.Chrome()

Если у вас есть объект драйвера, вы можете вызвать метод get() чтобы перейти на любую веб-страницу. Вот как перейти к конвертеру титров:

1
driver.get(‘https://titlecaseconverter.com’)

Нам нужен способ найти элементы на странице, с которой вы хотите взаимодействовать. Самый простой способ — просмотреть веб-страницу в браузере и найти идентификаторы целевых элементов. На следующем скриншоте видно, что поле ввода имеет идентификатор «title»:

Поиск элементов

Кнопка конвертации не имеет идентификатора, но это не проблема, как вы скоро увидите. Вот код для поиска формы и текстовых полей по id:

1
input_field = driver.find_element_by_id(‘title’)

Если элемент, с которым вы хотите взаимодействовать, не имеет идентификатора, вы можете найти его, используя различные другие методы, такие как имя, имя класса или селектор CSS. Посмотреть все варианты в этом руководстве Selenium .

Например, чтобы найти кнопку конвертации, я использовал ее имя класса:

1
2
convertButton = \
   driver.find_element_by_class_name(‘convertButton’)

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

1
2
input_field.clear()
input_field.send_keys(heading)

Это было довольно легко.

Теперь пришло время отправить форму. Вы можете сделать это двумя способами:

  • Найдите элемент формы на странице и вызовите его метод submit() .
  • Найдите кнопку конвертации и нажмите ее.

Я изначально отправил форму напрямую:

1
2
form = driver.find_element_by_css_selector(‘body > form’)
form.submit()

По какой-то причине это не работает. Там нет ошибки, но ничего не происходит. Я не тратил много времени на исследования, потому что весь смысл Selenium и этого урока в том, чтобы имитировать человека. Поэтому я использовал другой метод и просто нажал кнопку, которую нашел ранее:

1
convertButton.click()

Онлайновый конвертер кейсов несколько необычен Поле вывода не существует изначально. После того, как вы нажмете кнопку «Преобразовать» и форма будет отправлена, выходные данные отображаются вместе с кнопкой «Копировать». Это означает, что нам нужно дождаться завершения отправки формы, прежде чем появится кнопка копирования, и мы можем щелкнуть ее, чтобы скопировать вывод в буфер обмена.

Селен покрыл тебя. Он поддерживает ожидание произвольных условий и тайм-аут, если они не материализуются. Вот код, который ждет кнопку копирования. Он создает объект WebDriverWait с WebDriverWait таймаутом. Затем он создает условие для присутствия элемента с именем класса copyButton , а затем вызывает метод wait until() объекта ожидания с условием.

1
2
3
wait = WebDriverWait(driver, 5)
buttonPresent = presence_of_element_located((By.CLASS_NAME, ‘copyButton’))
copyButton = wait.until(buttonPresent)

В результате после нажатия кнопки конвертирования он будет ждать, пока не появится кнопка копирования или не истечет время ожидания через пять секунд. Если все хорошо, он вернет элемент copyButton .

Вы можете прочитать содержимое текстовых полей с помощью field.get_attribute('value') . Но, как я уже упоминал ранее, онлайн-конвертер кейсов довольно необычен. Его выходные данные представляют собой вложенную структуру span и div, и когда вы наводите указатель мыши на каждую часть выходных данных, он говорит вам, почему он пишется с большой буквы или нет.

Я мог бы свернуть этот лабиринт и разобрать фактический заголовок, но есть более простой способ. Кнопка копирования копирует заголовок с заглавной буквы в буфер обмена. Мы можем просто нажать на кнопку и прочитать заголовок из буфера обмена. Я использовал модуль буфера обмена, который можно установить с pipenv install clipboard . Приведенный ниже код очищает буфер обмена, копируя в него пустую строку, нажимает кнопку копирования и многократно читает буфер обмена, пока он не станет пустым.

1
2
3
4
5
6
clipboard.copy(»)
copyButton.click()
result = clipboard.paste()
while not result:
    time.sleep(0.1)
    result = clipboard.paste()

OK. Мы можем использовать один заголовок. Я поместил весь этот код в одну функцию:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def capitalize_heading(heading):
   input_field = driver.find_element_by_id(‘title’)
   input_field.clear()
   input_field.send_keys(heading)
 
   # form = driver.find_element_by_css_selector(‘body > form’)
   # form.submit()
 
   convertButton = \
       driver.find_element_by_class_name(‘convertButton’)
   convertButton.click()
 
   # Wait for copy button to appear
   wait = WebDriverWait(driver, 5)
   buttonPresent = presence_of_element_located((By.CLASS_NAME,
                                                ‘copyButton’))
   copyButton = wait.until(buttonPresent)
 
   clipboard.copy(»)
   copyButton.click()
   result = clipboard.paste()
   while not result:
       time.sleep(0.1)
       result = clipboard.paste()
 
   return result

Теперь, вооружившись этой возможностью, мы можем разобрать целую статью и использовать все заголовки. Я пишу свои уроки в Markdown. Все мои заголовки начинаются с одного или нескольких хэшей (#).

Я определил вспомогательную функцию, которая берет строку и, если она содержит заголовок, правильно использует ее capitalize_heading() используя функцию capitalize_heading() и возвращает результат. Главное — убрать все ведущие хеши и пробелы и восстановить их позже. Мы не можем указывать заголовок пробелами, потому что это сбивает с толку онлайн конвертер дел

1
2
3
4
5
6
7
8
def capitalize_line(line):
   tokens = line.split(‘#’)
   heading = tokens[-1]
   space_count = len(heading) — len(heading.lstrip())
   spacing = heading[:space_count]
   tokens[-1] = spacing + capitalize_heading(heading.lstrip())
   result = ‘#’.join(tokens)
   return result

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

def capitalize_all_headings(markdown) :
1
2
3
4
5
6
7
8
capitalized = []
   lines = markdown.split(‘\n’)
   for line in lines:
       if line.startswith(‘#’):
           line = capitalize_line(line)
           print(line)
       capitalized.append(line)
   return ‘\n’.join(capitalized)

Основная функция берет входной документ Markdown, использует его заглавные буквы и сохраняет результат как «capitalized.md», который вы можете проверить и использовать. Единственное, с чем следует быть осторожным, это если ваш документ Markdown содержит не заголовочные строки, начинающиеся с хеша. Это может произойти, если вы возглавляете блоки кода, содержащие комментарии Python или bash.

Забавный факт — урок, который вы сейчас читаете, был написан с использованием этой программы.

Автоматизация браузера позволяет программно управлять веб-приложениями, которые не предоставляют API. Это полезно в основном для заполнения форм и других интерактивных веб-действий (нажмите «Далее» в длинных лицензионных соглашениях?).

Selenium был в первую очередь предназначен для тестирования веб-приложений, но он отлично подходит для автоматизации любого взаимодействия на основе браузера. Если вы немного подумаете, вы можете найти множество веб-приложений, которые вы можете автоматизировать и сделать вашу жизнь проще.