2013-02-13 4 views
0

У меня есть текст HTML, который выглядит как много экземпляров следующей структуры:BeautifulSoup HTML извлечения данных с BeautifulSoup и Python

<DOC> 
<DOCNO> XXX-2222 </DOCNO> 
<FILEID>AP-NR-02-12-88 2344EST</FILEID> 
<HEAD>Reports Former Saigon Officials Released from Re-education Camp</HEAD> 
<TEXT> 
Lots of text here 
</TEXT> 
</DOC> 

Что мне нужно сделать, это индекс каждая структура, с DocNo, заголовок и текст , для последующего анализа (токенизация и т. д.).

Я думал об использовании BeautifulSoup, и это код, который я до сих пор:

soup = BeautifulSoup (file("AP880212.html").read()) 
num = soup.findAll('docno') 

Но это только дает мне результаты в следующем формате:

<docno> AP880212-0166 </docno>, <docno> AP880212-0167 </docno>, <docno> AP880212-0168 </docno>, <docno> AP880212-0169 </docno>, <docno> AP880212-0170 </docno> 

Как извлечь числа в пределах <>? И связать их с заголовками и текстами?

Большое спасибо,

Саше

ответ

1

Что-то вроде этого:

html = """<DOC> 
<DOCNO> XXX-2222 </DOCNO> 
<FILEID>AP-NR-02-12-88 2344EST</FILEID> 
<HEAD>Reports Former Saigon Officials Released from Re-education Camp</HEAD> 
<TEXT> 
Lots of text here 
</TEXT> 
</DOC> 
""" 

import bs4 

d = {} 

soup = bs4.BeautifulSoup(html, features="xml") 
docs = soup.findAll("DOC") 
for doc in docs: 
    d[doc.DOCNO.getText()] = (doc.HEAD.getText(), doc.TEXT.getText()) 

print d 
#{u' XXX-2222 ': 
# (u'Reports Former Saigon Officials Released from Re-education Camp', 
# u'\nLots of text here\n')} 

Обратите внимание, что я прохожу features="xml" конструктору. Это связано с тем, что на вашем входе много нестандартных html-тегов. Вероятно, вам также понадобится текст .strip(), прежде чем вы сохраните его в словаре, чтобы он не был настолько чувствительным к пробелу (если это не ваше намерение, конечно).

Update:

Если несколько Дока в том же файле, и features="xml" ограничивает до одного, его, вероятно, потому, что XML-анализатор ожидает иметь только один корневой элемент.

E.g. Если вы обернуть весь ввод XML в один корневой элемент, он должен работать:

<XMLROOT> 
    <!-- Existing XML (e.g. list of DOC elements) --> 
</XMLROOT> 

так что вы можете сделать это в файле, или то, что я хотел бы предложить, чтобы сделать это программно на входном тексте перед вами передать его BeautifulSoup:

root_element_name = "XMLROOT" # this can be anything 
rooted_html = "<{0}>\n{1}\n</{0}>".format(root_element_name, html) 
soup = bs4.BeautifulSoup(rooted_html, features="xml") 
+0

И если я хотел прочитать его из .html-файлов из каталога? В настоящее время я делаю путь = '/ TREC-AP88-90-qrels1-50/Документы' для INFILE в glob.glob (os.path.join (путь, '* HTML'.)): soup = BeautifulSoup (файл (infile) .read(), features = "xml") , а затем ваш код, но это не дает мне правильных результатов. – user2070177

+0

кажется, что только найдет первый «документ», даже если в документе больше ... – user2070177

+0

Фактически, это часть «xml», которая заставляет ее останавливаться после первого документа .. есть ли способ обойти это? – user2070177

2

чтобы получить содержимое тегов:

docnos = soup.findAll('docno') 
for docno in docnos: 
    print docno.contents[0] 
+0

, и если бы я хотел связать документы docs, заголовки и документы? – user2070177

+0

Вы можете перебирать 'soup.findAll ('doc')', собирая содержимое тега, которое вы хотите, перед итерацией по 'soup.findAll ('docno')' и создавая ключи в первом цикле и устанавливая значения во втором цикле. То есть иметь вложенный цикл (не дополнительный цикл). – That1Guy

+0

Также рассмотрите использование 'BeautifulStoneSoup', так как это xml. Его легко использовать (как и BeautifulSoup). Сделайте 'из BeautifulSoup импорт BeautifulStoneSoup' и используйте его точно так же, как обычно. – That1Guy

0
docnos = soup.findAll('docno') 
for docno in docnos: 
     print docno.renderContents() 

Yo u также может использовать renderContents() для извлечения информации из тегов.

Смежные вопросы