Kodomo

Пользователь

Учебная страница курса биоинформатики,
год поступления 2013

Параметры командной троки. Работа с html в python

Работа с html в python

Модули стандартной библиотеки питона для открытия web-документов - urllib2, urllib. Работа с html документами аналогична работе с файлами. Базовые операции - открытие, чтение и закрытие документа.

   1 import urllib2
   2 html_filelike_object = urllib2.urlopen("http://www.genboree.org/EdaccData/Current-Release/study-sample-experiment/UW/Fetal_Lung/Expression_Array/")
   3 html = html_filelike_object.read()
   4 html_filelike_object.close()

Открытие 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).

   1 from html.parser import HTMLParser
   2 
   3 class MyHTMLParser(HTMLParser):
   4     def handle_starttag(self, tag, attrs):
   5         print("Encountered a start tag:", tag)
   6     def handle_endtag(self, tag):
   7         print("Encountered an end tag :", tag)
   8     def handle_data(self, data):
   9         print("Encountered some data  :", data)

В метод handle_starttag() передается два аргумента - имя тэга, и список атрибутов элемент, представленных в виде списка кортежей пар (имя_атрибута, значение). Методы handle_endtag() и handle_data работают с именами тэгов. Методы getpos() и get_starttag_text()возвращают соответственно номер обрабатываемой строки и имя предыдущего последнего открытого тэга. После определения поведения парсера создается элемент заданного класса. В методе feed()обьекту класса передается разбираемый html-документ. Необходимо закрытие обработки html - вызов метода close().

   1 parser = MyHTMLParser()
   2 parser.feed(‘html’)
   3 parser.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 представляет собой путь к файлу, его содержимое сохранить в файл на компьютере.

   1 url='file.gz'
   2 u = urllib2.urlopen(url)
   3 f = open(file_name, 'wb')
   4 f.write(u.read())
   5 f.close()
   6 u.close()

В модуле urllib также есть метод urlretrive(), принимающий в качестве параметров url и имя записываемого файла, также в качестве параметра можно передать функцию, которая будет вызвана в начале записи и через определенные промежутки записи блоков некоторого размера в выходной файл. Функция должна принимать три параметра - количество прочитанных блоков, размер блока, размер файла. Прописывание этой функции позволяет отслеживать прогресс закачки файла.

   1 urllib.urlretrieve(url, 'local_file_name', reporthook=some_progress_bar_function)

Еще когда нам может понадобиться работа с web – это отправка поисковых запросов, а также заполнение форм. Пример, демонстрирующий работу метода Request() модуля urllib2:

   1 import urllib
   2 import urllib2
   3 
   4 url = 'http://www.someurl’
   5 
   6 values = {'name' : 'Michael’,
   7           'location' : 'Russia'}
   8 
   9 data = urllib.urlencode(values)
  10 req = urllib2.Request(url, data)
  11 response = urllib2.urlopen(req)
  12 the_page = response.read()

Метод отправляет данные поля формы, затем можно получить результат отправленного запроса.

Разбор командной строки

Когда мы вызываем программу через командную строку, мы можем также указывать ее параметры (если они есть).

Например, вспомним команду ls. Ее можно вызвать с различными параметрами.

ls -lR
ls --long --recursive
ls -l -R

Все три записи выше равнозначны между собой.

ls --sort=time # параметры могут принимать какое-то значение
ls a.txt b.txt

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

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

ls -l /home
# /home - позиционный аргумент, имя папки в которой нужно перечислить файлы,
# -l - именованный аргумент, параметр запуска ls

python script.py
# с точки зрения командной строки, вы запускаете программу python, получающую на вход позиционный аргумент, имя файла для выполнения

1. sys.argv: Если достаточно только позиционных аргументов, то можно воспользоваться переменной sys.agrv. В ней в виде списка строк содержится все то, что было написано в командной строке (разделенное по пробелам).

Напишем маленькую программу test_argv.py:

import sys
print sys.argv

Запуск:
python test_argv.py file.txt -r -w 5

Результат:
['test_argv.py', 'file.txt', '-r', '-w', '5']

* обратите внимание, а) все параметры - строки, даже те, которые представляют собой числа; б) имя скрипта также является параметром, поскольку на самом деле вы запускаете не ваш скрипт, а python, а ваш скрипт - это позиционный параметр для его запуска (см. также выше).

2. argparse: Для того, чтобы автоматизировать разбор командной строки, и иметь возможность легко работать с именованными параметрами (что удобно, поскольку при этом не нужно помнить, в каком порядке вы должны прописывать параметры), используется библиотека argparse.

Она позволяет использовать как позиционные, так и именованные аргументы. Используйте нижеприведенные заготовки кода для работы. В результате их выполнения переменные заданных типов окажутся в соответствующих переменных структуры args.

а. Для позиционных аргументов:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("r1", type=int,  # first argument
                    help="display help to r1")
parser.add_argument("name", type=str,  # second argument
                    help="display help to name")
args = parser.parse_args()

print(args.r1)
print(args.name)

Запуск:
python my_script.py 2 Hello

Результат:
2
Hello

Метод библиотеки agparse .ArgumentParser() создает специальный объект, называемый парсером.

Метод parser.add_argument() этого объекта позволяет создавать описания переменных, которые будут потом читаться из командной строки. Этот метод принимает на вход имя будущей переменной, ее тип и другие параметры.

б. Для именованных параметров почти ничего не меняется, но вместо имени переменной нужно написать «--имя_переменной». Вы также можете дополнительно указать «-короткое_имя», для удобства использования:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-r1", "--realvalue1", type=int,
                    help="This is r1")
parser.add_argument("--name", type=str,
                    help="This is a great name")
args = parser.parse_args()

print(args.realvalue1)
print(args.name)

Запуск (все 4 варианта идентичны):
python my_script.py --realvalue1 2 --name Hello
или
python my_script.py --name Hello --realvalue1 2
или
python my_script.py -r1 2 --name Hello
или
python my_script.py --name Hello -r1 2

Результат:
2
Hello

Вы также можете направлять входные параметры в переменные с названием, отличным от того, которое используете в качестве ключа в командной строке. Для этого используется параметр dest метода .add_argument(). Чтобы попробовать – замените строку parser.add_argument для r1 на:

parser.add_argument("-r1", "--realvalue1", type=int, dest="i",
                    help="This is r1, which value will be saved in args.i")

и print(args.realvalue1) на:

print(args.i)

и посмотрите на результат.

в. Вы также можете задавать значение переменной по умолчанию, с помощью параметра default:

parser.add_argument("-r1", "--realvalue1", type=int, dest="i",
                    default=3, help="This is r1, saved to args.i, with default value = 3")

Запуск:
python my_script.py -r1 2 --name Hello

Результат
2
Hello

А теперь не указываем значение для r1
python my_script.py --name Hello

Результат:
3
Hello

г. Приятный бонус, или зачем нам параметр 'help' внутри parser.add_argument:

Запустите программу следующим образом:

python my_script.py -h

и посмотрите на результат.