К сожалению, это будет немного сложно, потому что в этом формате есть некоторые данные, которые вам нужны, и они не сохраняются четкими маркерами.
Модель данных
Кроме того, ваше понимание вложенности не совсем верно. Фактическая структура католической церкви (не эта структура документа) больше похожа на:
District (also called deanery or vicariate. In this case they all seem to be Vicariates Forane.)
Cathedral, Parish, Oratory
Обратите внимание, что не требуется , чтобы приход попал под район / деканат, хотя они обычно это делают. Я думаю, что в документе говорится, что все, что перечислено после Района, принадлежит этому району, но вы не можете знать наверняка.
Там также есть запись, которая является не Церковью, а общиной (филиппинско-китайская община Сан-Лоренцо). Они не имеют четкой идентичности или управления в церкви (т. Е. Это не здание) - скорее, это не-территориальная группа людей, о которой капеллану поручено заботиться.
Синтаксический
Я думаю, что вы должны использовать пошаговый подход:
- найти все элементы
li
, каждый из которых является "элементом"
- название элемента - первый текстовый узел
- найти все элементы
i
: это ключи, значения атрибутов, строки столбцов и т. Д.
- весь текст до следующего
i
(разделенный br
) является значением для этого ключа.
Одна особая проблема с этой страницей в том, что ее html настолько патологически плохой , что вам нужно использовать MinimalSoup
для правильного его анализа. В частности, BeautifulSoup
считает, что li
элементы вложены, потому что в документе нет ol
или ul
!
Этот код даст вам список списков кортежей. Каждый кортеж представляет собой пару ('key','value')
для элемента.
Если у вас есть такая структура данных, вы можете нормализовать, преобразовать, вложить и т. Д., Как вам нравится, и оставить HTML-код позади.
from BeautifulSoup import MinimalSoup
import urllib
fp = urllib.urlopen("http://www.ucanews.com/diocesan-directory/html/ordinary-of-philippine-cagayandeoro-parishes.html")
html = fp.read()
fp.close()
soup = MinimalSoup(html);
root = soup.table.tr.td
items = []
currentdistrict = None
# this loops through each "item"
for li in root.findAll(lambda tag: tag.name=='li' and len(tag.attrs)==0):
attributes = []
parishordistrict = li.next.strip()
# look for string "district" to determine if district; otherwise it's something else under the district
if parishordistrict.endswith(' District'):
currentdistrict = parishordistrict
attributes.append(('_isDistrict',True))
else:
attributes.append(('_isDistrict',False))
attributes.append(('_name',parishordistrict))
attributes.append(('_district',currentdistrict))
# now loop through all attributes of this thing
attributekeys = li.findAll('i')
for i in attributekeys:
key = i.string # normalize as needed. Will be 'Address:', 'Parochial Victor:', etc
# now continue among the siblings until we reach an <i> again.
# these are "values" of this key
# if you want a nested key:[values] structure, you can use a dict,
# but beware of multiple <i> with the same name in your logic
next = i.nextSibling
while next is not None and getattr(next, 'name', None) != 'i':
if not hasattr(next, 'name') and getattr(next, 'string', None):
value = next.string.strip()
if value:
attributes.append((key, value))
next = next.nextSibling
items.append(attributes)
from pprint import pprint
pprint(items)