Получить весь контент между закрывающим и открывающим тегом html, используя Beautiful Soup - PullRequest
2 голосов
/ 04 января 2012

Я анализирую контент, используя Python и Beautiful Soup, затем записываю его в файл CSV и столкнулся с проблемой получения определенного набора данных.Данные проверяются с помощью созданной мной реализации TidyHTML, а затем удаляются другие ненужные данные.

Проблема в том, что мне нужно получить все данные между набором <h3> тегов.

Образец данных:

<h3><a href="Vol-1-pages-001.pdf">Pages 1-18</a></h3>
<ul><li>September 13 1880. First regular meeting of the faculty;
 September 14 1880. Discussion of curricular matters. Students are
 debarred from taking algebra until they have completed both mental
 and fractional arithmetic; October 4 1880.</li><li>All members present.</li></ul>
 <ul><li>Moved the faculty henceforth hold regular weekkly meetings in the
 President's room of the University building; 11 October 1880. All
 members present; 18 October 1880. Regular meeting 2. Moved that the
 President wait on the property holders on 12th street and request
 them to abate the nuisance on their property; 25 October 1880.
 Moved that the senior and junior classes for rhetoricals be...</li></ul>
 <h3><a href="Vol-1-pages-019.pdf">Pages 19-33</a></h3>`

Мне нужно получить всесодержимое между первым закрывающим тегом </h3> и следующим открывающим тегом <h3>.Это не должно быть трудно, но моя толстая голова не устанавливает необходимые связи.Я могу захватить все теги <ul>, но это не работает, потому что между тегами <h3> и <ul> нет отношения один к одному.

Вывод, который я хочу получить:

Pages 1-18 | Vol-1-pages-001.pdf | содержимое между тегами.

Первые две части не были проблемой, но содержание между набором тегов мне сложно.

Мой текущий код выглядит следующим образом:

import glob, re, os, csv
from BeautifulSoup import BeautifulSoup
from tidylib import tidy_document
from collections import deque

html_path = 'Z:\\Applications\\MAMP\\htdocs\\uoassembly\\AssemblyRecordsVol1'
csv_path = 'Z:\\Applications\\MAMP\\htdocs\\uoassembly\\AssemblyRecordsVol1\\archiveVol1.csv'

html_cleanup = {'\r\r\n':'', '\n\n':'', '\n':'', '\r':'', '\r\r': '', '<img src="UOSymbol1.jpg"    alt="" />':''}

for infile in glob.glob( os.path.join(html_path, '*.html') ):
    print "current file is: " + infile

    html = open(infile).read()

    for i, j in html_cleanup.iteritems():
            html = html.replace(i, j)

    #parse cleaned up html with Beautiful Soup
    soup = BeautifulSoup(html)

    #print soup
    html_to_csv = csv.writer(open(csv_path, 'a'), delimiter='|',
                      quoting=csv.QUOTE_NONE, escapechar=' ')  
    #retrieve the string that has the page range and file name
    volume = deque()
    fileName = deque()
    summary = deque()
    i = 0
    for title in soup.findAll('a'):
            if title['href'].startswith('V'):
             #print title.string
             volume.append(title.string)
             i+=1
             #print soup('a')[i]['href']
             fileName.append(soup('a')[i]['href'])
             #print html_to_csv
             #html_to_csv.writerow([volume, fileName])

    #retrieve the summary of each archive and store
    #for body in soup.findAll('ul') or soup.findAll('ol'):
    #        summary.append(body)
    for body in soup.findAll('h3'):
            body.findNextSibling(text=True)
            summary.append(body)

    #print out each field into the csv file
    for c in range(i):
            pages = volume.popleft()
            path = fileName.popleft()
            notes = summary
            if not summary: 
                    notes = "help"
            if summary:
                    notes = summary.popleft()
            html_to_csv.writerow([pages, path, notes])

Ответы [ 2 ]

0 голосов
/ 05 января 2012

Извлечение содержимого между тегами </h3> и <h3>:

from itertools import takewhile

h3s = soup('h3') # find all <h3> elements
for h3, h3next in zip(h3s, h3s[1:]):
  # get elements in between
  between_it = takewhile(lambda el: el is not h3next, h3.nextSiblingGenerator())
  # extract text
  print(''.join(getattr(el, 'text', el) for el in between_it))

Код предполагает, что все элементы <h3> являются родственными. Если это не так, вы можете использовать h3.nextGenerator() вместо h3.nextSiblingGenerator().

0 голосов
/ 04 января 2012

Если вы попытаетесь извлечь данные между тегами <ul><li></ul></li> в lxml, это обеспечит большую функциональность использования CSSSelector

import lxml.html
import urllib
data = urllib.urlopen('file:///C:/Users/ranveer/st.html').read() //contains your html snippet
doc = lxml.html.fromstring(data)
elements = doc.cssselect('ul li') // CSSpath[using firebug extension]
for element in elements:
      print element.text_content()    

после выполнения вышеуказанного кода вы получите весь текст между тегами ul,li. Это намного чище, чем красивый суп.

Если вы случайно планируете использовать lxml, вы можете оценить выражения XPath следующим образом-

import lxml
from lxml import etree
content = etree.HTML(urllib.urlopen("file:///C:/Users/ranveer/st.html").read())
content_text = content.xpath("html/body/h3[1]/a/@href | //ul[1]/li/text() | //ul[2]/li/text() | //h3[2]/a/@href")
print content_text

Вы можете изменить XPath в соответствии со своими потребностями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...