Учебная страница курса биоинформатики,
год поступления 2014
Параметры командной троки. Работа с html в python
Разбор командной строки
Когда мы вызываем программу через командную строку, мы можем также указывать ее параметры (если они есть).
Например, вспомним команду ls. Ее можно вызвать с различными параметрами.
ls -lR ls --long --recursive ls -l -R
Все три записи выше равнозначны между собой.
ls --sort=time # параметры могут принимать какое-то значение ls a.txt b.txt
Если параметр написан через знак дефиса, то он называется именованным, иначе – позиционным.
В переменной sys.argv содержится список строк - все то, что было написано в командной строке (разделенное по пробелам).
Например, если мы напишем маленькую программку test_argv.py:
И запустим ее с какими-нибудь параметрами, то получится так:
Для того, чтобы автоматизировать разбор командной строки подобно программе ls, надо импортировать библиотеку argparse.
parser - это так называемый объект-разборщик (далее будем называть его просто парсером).
Разберем это на примере программы сортировки (пусть будет называться sort.py).
Пусть для нее можно будет указывать три параметра:
-r --reverse -w --word -a --sort-alg
Для этого надо прописать:
1 import argparse
2 import sys
3 parser=argparse.ArgumentParser()
4 parser.add_argument('-w', '--word', help='word number to sort by', type=int)
5 parser.add_argument('-r', '--reverse', action='store_true', help='reverse sort order')
6 parser.add_argument('-a', '--sort-alg', dest='alg', help='sorting algorithm; can be "qsort" (qsort) or "merge" (merge-sort)', type=str, default='qsort')
7 options=parser.parse_args()
8 print(options)
9 print(options.word)
10 print(options.alg)# значение положилось в options.alg, как это указано в 'dest'
11 print(options.reverse)
12 print sys.argv
Итак, парсер будет разбирать слово, стоящее после записи '-w' ('--word'), '-a' ('--sort-alg') или '-r' ('--reverse'). Для '-w' оно должно быть целым числом, для '-a' - строкой и по умолчанию равно 'qsort'.
Фраза action='store_true' означает, что данный параметр является флагом. Если бы этого не было, то параметр нёс бы какое-то значение.
Рассмотрим диалог с командной строкой:
$ python sort.py Namespace(alg='qsort', reverse=False, word=None) None qsort False ['test1.py'] $ python sort.py --help Usage: sort.py [options] Options: -h, --help show this help message and exit -w WORD, --word=WORD word number to sort by -r, --reverse reverse sort order -a ALG, --sort-alg=ALG sorting algorithm; can be "qsort" (qsort) or "merge" (merge-sort) $ python sort.py -x sort.py [options] sort.py: error: unrecognized arguments: -x
Мы можем захотеть как-то реагировать на отсутствие значения для обязательного параметра (например, параметра '-w'):
1 import argparse
2 import sys
3 parser=argparse.ArgumentParser()
4 parser.add_argument('-w', '--word', help='word number to sort by', type=int)
5 parser.add_argument('-r', '--reverse', action='store_true', help='reverse sort order')
6 parser.add_argument('-a', '--sort-alg', dest='alg', help='sorting algorithm; can be "qsort" (qsort) or "merge" (merge-sort)', type=str, default='qsort')
7 options=parser.parse_args()
8 print(options.word)
9 if not options.word:
10 parser.error('Word number is not given')
Тогда диалог с командной строкой будет выглядеть так:
$ python sort.py None Usage: sort.py [options] sort.py: error: Word number is not given $ python sort.py -w 3 3
Работа с html в python
При работе бывает необходимо извлекать информацию из html страниц. Модули стандартной библиотеки питона для открытия web-документов - urllib2, urllib. Работа с html документами аналогична работе с файлами. Базовые операции - открытие, чтение и закрытие документа.
Открытие url осуществляется методом urlopen(), метод возвращает информацию о странице, представленную в обьекте аналогичном файловому. Чтение - методами read() (в одну строку) и readlines()(в список строк). Также как при работе с файлами необходимо закрытие html-документа. Прочитанная веб-страница представляет собой html текст - набор элементов, заключенных в тэги(открывающие(<html>, <head>, <a>) и закрывающие </html>, </head>… ). Некоторые элементы также имеют различные дополнительные атрибуты, которые указываются в открывающем тэге элемента.
1 <tag attribute1="value1" attribute2="value2" >
Для работы с информацией внутри тэгов можно использовать классы-разборщики. Вообще, существует большое количество библиотек для удобного разбора подобных документов (lxml, Beautiful Soup). Стандартная библиотека python для работы с такими документами - HTMLParser (html.parser в Python 3). В модуле HTMLParser определяется класс HTMLParser. Этот класс включает стандартные методы, которые обрабатывают ситуации встречи открывающих тэгов, данных элемента, закрывающих тэгов, комментариев и тд. Чтобы описать те операции, которые должны совершаться программой в каком либо из этих случаев(встрече открывающего тэга) пользователь должен определить собственный подкласс, наследующий от класса HTMLParser, и описать в нем работу соответствующих методов - handle_starttag(tag, attrs), handle_endtag(tag), handle_data(data). Таким образом, мы можем описывать действия, которые нужно выполнить при встрече открывающего тэга, закрывающего тэга и при разборе содержимого между этими тэгами.
В метод handle_starttag() передается два аргумента - имя тэга, и список атрибутов элемента, представленных в виде списка кортежей пар (имя_атрибута, значение). Методы handle_endtag() и handle_data работают с именами тэгов. Т.е., можно задать действия в случае встречи закрывающего тэга с определенным названием. Другие полезные методы класса HTMLParser – getpos() и get_starttag_text(), они возвращают соответственно номер обрабатываемой строки и имя предыдущего последнего открытого тэга.
После описания действий нашего разборщика создается элемент заданного класса. В методе feed()объекту класса передается разбираемый html-документ. В конце необходимо закрытие обработки html - вызов метода close().
Пример 1. Записываем данные из таблицы html:
1 h = '''<body><table><tr><td>Cell 1</td><td>Cell 2</td></tr><tr><td>Cell 3</td><td>Cell 4</td></tr></table></body>'''
2
3 class MyParser(HTMLParser):
4 #def __init__(self):
5 def reset(self):
6 HTMLParser.reset(self)
7 #HTMLParser.__init__(self)
8 self.table_content = []
9 self.table_row = []
10
11
12 def handle_endtag(self,tag):
13 if tag == "tr":
14 self.table_content.append(self.table_row)
15 self.table_row = []
16
17 def handle_data(self, data):
18 if self.get_starttag_text() == "<td>":
19 self.table_row.append(data)
20
21 p=MyParser()
22 p.feed(h)
23 p.close()
24
25
26 >>> p.table_content
27 [['Cell 1', 'Cell 2'], ['Cell 3', 'Cell 4']]
Обратите внимание, что вместо вызова init класса может быть более корректным вызвать собственный метод класса HTMLParser - reset().
Если url представляет собой путь к файлу, его содержимое можно сохранить в файл на компьютере.
В модуле urllib также есть метод urlretrive(), принимающий в качестве параметров url и имя записываемого файла, также в качестве параметра можно передать функцию, которая будет вызвана в начале записи и через определенные промежутки записи блоков некоторого размера в выходной файл. Функция должна принимать три параметра - количество прочитанных блоков, размер блока, размер файла. Прописывание этой функции позволяет отслеживать прогресс закачки файла.
1 urllib.urlretrieve(url, 'local_file_name', reporthook=some_progress_bar_function)
Еще когда нам может понадобиться работа с web – это отправка поисковых запросов, а также заполнение форм. Пример, демонстрирующий работу метода Request() модуля urllib2:
Метод отправляет данные поля формы, затем можно получить результат отправленного запроса.