BeautifulSoup (Python) и разбор HTML таблицы - PullRequest
2 голосов
/ 25 января 2011

##### Обновление ###### : renderContents () вместо содержимого [0] добились цели. Я все равно оставлю это открытым, если кто-то может предложить лучшее, элегантное решение!

Я пытаюсь проанализировать количество веб-страниц на предмет требуемых данных. В таблице нет тега класса / идентификатора. Поэтому я должен искать «веб-сайт» в содержании tr.

Проблема под рукой: Отображение td.contents отлично работает только с текстом, но не с гиперссылками по какой-то причине? Что я делаю неправильно? Есть ли лучший способ сделать это с помощью bs в Python?

Те, кто предлагает lxml, у меня есть постоянный поток здесь Установка centOS и lxml без прав администратора в настоящее время оказывается весьма полезной. Следовательно, исследуем опцию BeautifulSoup.

Образец HTML:

                   <table border="2" width="100%">
                      <tbody><tr>
                        <td width="33%" class="BoldTD">Website</td>
                        <td width="33%" class="BoldTD">Last Visited</td>
                        <td width="34%" class="BoldTD">Last Loaded</td>
                      </tr>
                      <tr>
                        <td width="33%">
                          <a href="http://google.com"></a>
                        </td>
                        <td width="33%">01/14/2011
                                </td>
                        <td width="34%">
                                </td>
                      </tr>
                      <tr>
                        <td width="33%">
                          stackoverflow.com
                        </td>
                        <td width="33%">01/10/2011
                                </td>
                        <td width="34%">
                                </td>
                      </tr>
                      <tr>
                        <td width="33%">
                          <a href="http://stackoverflow.com"></a>
                        </td>
                        <td width="33%">01/10/2011
                                </td>
                        <td width="34%">
                                </td>
                      </tr>
                    </tbody></table>

Код Python:

        f1 = open(PATH + "/" + FILE)
        pageSource = f1.read()
        f1.close()
        soup = BeautifulSoup(pageSource)
        alltables = soup.findAll( "table", {"border":"2", "width":"100%"} )
        print "Number of tables found : " , len(alltables)

        for table in alltables:
            rows = table.findAll('tr')
            for tr in rows:
                cols = tr.findAll('td')
                for td in cols:
                    print td.contents[0]

Ответы [ 2 ]

1 голос
/ 25 января 2011
from BeautifulSoup import BeautifulSoup

pageSource='''...omitted for brevity...'''    

soup = BeautifulSoup(pageSource)
alltables = soup.findAll( "table", {"border":"2", "width":"100%"} )

results=[]
for table in alltables:
    rows = table.findAll('tr')
    lines=[]
    for tr in rows:
        cols = tr.findAll('td')
        for td in cols:
            text=td.renderContents().strip('\n')
            lines.append(text)
    text_table='\n'.join(lines)
    if 'Website' in text_table:
        results.append(text_table) 
print "Number of tables found : " , len(results)
for result in results:
    print(result)

урожайность

Number of tables found :  1
Website
Last Visited
Last Loaded
<a href="http://google.com"></a>
01/14/2011

stackoverflow.com
01/10/2011

<a href="http://stackoverflow.com"></a>
01/10/2011

Это близко к тому, что вы ищете?Проблема была в том, что td.contents возвращает список NavigableStrings и суп tags.Например, выполнение print(td.contents) может привести к

['', '<a href="http://stackoverflow.com"></a>', '']

Так что, выделив первый элемент списка, вы пропустите тег <a>.

1 голос
/ 25 января 2011

Я ответил на аналогичный вопрос здесь .Надеюсь, это поможет вам.

Решение для непрофессионала:

alltables = soup.findAll( "table", {"border":"2", "width":"100%"} )

t = [x for x in soup.findAll('td')]

[x.renderContents().strip('\n') for x in t]

Вывод:

['Website',
 'Last Visited',
 'Last Loaded',
 '<a href="http://google.com"></a>',
 '01/14/2011\n                                ',
 '',
 '                          stackoverflow.com\n                        ',
 '01/10/2011\n                                ',
 '',
 '<a href="http://stackoverflow.com"></a>',
 '01/10/2011\n                                ',
 '']
...