Чтение официальных данных о численности муниципальных образований с параметрами форматирования текста с помощью библиотеки xlrd

от автора

Для одного общественного проекта (визуализация бюджетов поселений и районов) мне потребовались данные об иерархии муниципальных образований и их численности.
Нужные данные я нашел, но форма их представления для корректного использования оставляла желать лучшего.
Все необходимые данные были в одном файле, однако, его форматирование затрудняло извлечение иерархии. Все названия муниципалитетов, районов и областей располагались в одном столбце и отличались только форматом ячейки и шрифта. Область выделялась жирным шрифтом, район — жирным наклонным, а поселение имело отступ. Также в файле находились несколько ошибок, например один район был выделен как область (или наоборот, уже не помню), а еще в одном месте в середине названия образования встретился переход строки (этот момент выяснился на этапе импорта в Google App Engine, когда db.StringProperty() ругнулся на multiline), исходный файл в этих местах пришлось исправить.

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

Ячейка

alignment (XFAlignment object):
hor_align: 0
indent_level: 0
rotation: 0
shrink_to_fit: 0
text_direction: 0
text_wrapped: 0
vert_align: 2
background (XFBackground object):
background_colour_index: 65
fill_pattern: 0
pattern_colour_index: 64
border (XFBorder object):
bottom_colour_index: 64
bottom_line_style: 7
diag_colour_index: 0
diag_down: 0
diag_line_style: 0
diag_up: 0
left_colour_index: 64
left_line_style: 1
right_colour_index: 64
right_line_style: 1
top_colour_index: 64
top_line_style: 1
font_index: 7
format_key: 0
is_style: 0
lotus_123_prefix: 0
parent_style_index: 0
protection (XFProtection object):
cell_locked: 1
formula_hidden: 0
xf_index: 556

Шрифт

struck_out: 0
underline_type: 0
underlined: 0
weight: 400
bold: 1
character_set: 204
colour_index: 32767
escapement_type: 0
family: 0
font_index: 10
height: 200
italic: 1
name: u’Arial Cyr’
outline: 0
shadow: 0

Со всеми параметрами я не разбирался, мне для данной задачи хватило типа шрифта и отступа (ident) в ячейке. Но видно, что возможности большие, вплоть до цвета конкретной границы ячейки или типа линии.

Код скрипта

# -*- coding: utf-8 -*- from __future__ import unicode_literals import xlrd import json   rb = xlrd.open_workbook('Tabl-35-12.xls', formatting_info=True) font_list = rb.font_list  # list of all fonts in excel table sheet = rb.sheet_by_index(1) rows_number = sheet.nrows  peoples_dict = {}  # main dict for rownum in range(7, rows_number):  # data starts with line 7     cell = sheet.cell(rownum, 0)     value = cell.value.strip().replace('\n', ' ')  # delete spaces at start and end     peoples_count = sheet.cell(rownum, 1).value     if peoples_count == 0 or peoples_count == '':  # empty row - continue         continue     peoples_count = int(peoples_count)  # from 12313.0 to integer      cell_format = rb.xf_list[cell.xf_index]     current_font = font_list[cell_format.font_index]          bold = bool(current_font.bold)     italic = bool(current_font.italic)     indent = cell_format.alignment.indent_level      is_region = bold and not italic     is_raion = bold and italic     is_municipal = (indent == 2)      if is_region:         region = value         peoples_dict[region] = {'count': peoples_count}     elif is_raion:         raion = value         peoples_dict[region][raion] = {'count': peoples_count}     elif is_municipal:         municipal = value         peoples_dict[region][raion][municipal] = {'count': peoples_count}  print peoples_dict['Московская область']['Истринский муниципальный район']['Городское поселение Истра']['count']  with open('peoples.json', 'w') as outfile:     json.dump(peoples_dict, outfile) 

В качестве бонуса — получившийся выходной файл, в формате json. Структура — вложенные словари, где каждый элемент содержит ключ ‘count’, где записана численность образования, и ключи его потомков.
То есть численность Московской области можно получить так:

peoples_dict['Московская область']['count'] 

а численность города Истры Истринского муниципального района — так:

peoples_dict['Московская область']['Истринский муниципальный район']['Городское поселение Истра']['count'] 

ссылка на оригинал статьи http://habrahabr.ru/post/182548/