Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 19, 2009 14:54:57

andreykyz
От:
Зарегистрирован: 2009-11-19
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

сам код:

import urllib2
import html5lib
from html5lib import treebuilders

parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))
soup = parser.parse(urllib2.urlopen("http://a-el.ru/catalog.htm").read())
soup = parser.parse(f)
table_soup = soup.table.tbody.tr.td.table.tbody.tr.nextSibling.nextSibling.tbody
for tag in table_soup:
print tag.contents[0].name
Ошибка:
/var/lib/python-support/python2.6/html5lib/inputstream.py:367: DeprecationWarning: object.__init__() takes no parameters
str.__init__(self, value)
Traceback (most recent call last):
File "./examles.py", line 9, in <module>
print tag.contents[0].name
File "/var/lib/python-support/python2.6/BeautifulSoup.py", line 427, in __getattr__
raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr)
AttributeError: 'NavigableString' object has no attribute 'contents'
непонимаю в чем проблема.



Офлайн

#2 Ноя. 19, 2009 15:04:45

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

andreykyz
'NavigableString' object has no attribute ‘contents’
В BeautifulSoup есть два принципиально разных вида объектов Tag и NavigableString. Разница в том, что Navigable string соответствует текстовой строке и не имеет атрибута contents (по нему нельзя производить поиск в глубину, так как это уже “листик” дерева элементов)
andreykyz
print tag.contents.name
Судя по всему, вылетает здесь, когда в переменной ‘tag’ попадает не тег, а строковое значение
import urllib2
import html5lib
from html5lib import treebuilders

parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))
soup = parser.parse(urllib2.urlopen("http://a-el.ru/catalog.htm").read())
soup = parser.parse(f)
table_soup = soup.table.tbody.tr.td.table.tbody.tr.nextSibling.nextSibling.tbody
for tag in table_soup:
if isinstance(tag, Tag):
print tag.contents[0].name
В таком случае, этот код выведет имена тегов, и пропустит все строки



Офлайн

#3 Ноя. 19, 2009 15:21:08

andreykyz
От:
Зарегистрирован: 2009-11-19
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

regall
В BeautifulSoup есть два принципиально разных вида объектов Tag и NavigableString. Разница в том, что Navigable string соответствует текстовой строке и не имеет атрибута contents (по нему нельзя производить поиск в глубину, так как это уже “листик” дерева элементов)
хм понятно.
Тогда может быть подскажете как мне обойти все строчки таблицы и получать не просто string'и, а такие объекты чтобы можно было дальше в глубину по дереву уходить. В общем мне надо распарсить данную таблицу сначала по строчкам, а потом по ячейкам.



Офлайн

#4 Ноя. 19, 2009 15:36:40

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

trs = soup.findAll(name = "tr")
В результате этого кода вы получите все ветки <tr> {много тегов <td>} </tr>
for tr in trs:
tds = tr.findAll(name = "td")
В tds - получите все теги <td/> в теге <tr/>.

P.S. Также очень полезен бывает следующий вызов
allTags = soup.findAll(True)
Параметр True указывает парсеру найти абсолютно все теги документа (только теги, не строки)



Отредактировано (Ноя. 19, 2009 15:38:20)

Офлайн

#5 Ноя. 19, 2009 15:53:13

andreykyz
От:
Зарегистрирован: 2009-11-19
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

теперь вот такая ошибка:

    print tds
UnicodeEncodeError: 'ascii' codec can't encode characters in position 233-239: ordinal not in range(128)
странно, когда я делал:
soup = parser.parse(open("catalog.htm"))
table_soup = soup.table.tbody.tr.td.table.tbody.tr.nextSibling.nextSibling.tbody
print table_soup.tr
все выводилось без ошибок и по Русски



Офлайн

#6 Ноя. 19, 2009 16:16:03

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

andreykyz
UnicodeEncodeError: ‘ascii’ codec can't encode characters in position 233-239: ordinal not in range(128)
Эта ошибка описана в документации
http://www.crummy.com/software/BeautifulSoup/documentation.html#Troubleshooting
В качестве workaround попробуйте вывести результат не в консоль, а в файл и там уже смотреть.

P.S. проблемы с кодировками в Python 2.x неоднократно обсуждались на этом форуме, не поленитесь воспользоваться, гарантирую, что найдете для себя много полезной информации



Офлайн

#7 Ноя. 21, 2009 13:14:31

andreykyz
От:
Зарегистрирован: 2009-11-19
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib2
import html5lib
from html5lib import treebuilders

parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))
soup = parser.parse(urllib2.urlopen("http://a-el.ru/catalog.htm").read())
table_soup = soup.table.tbody.tr.td.table.tbody.tr.nextSibling.nextSibling.tbody

print table_soup.tr #вот это работает

trs = soup.findAll(name = "tr")
for tr in trs:
tds = tr.findAll(name = "td")
print unicode(str(tds), 'cp1251') #вот это не работает
/var/lib/python-support/python2.6/html5lib/inputstream.py:367: DeprecationWarning: object.__init__() takes no parameters
str.__init__(self, value)
<tr><th colspan="5" align="center" class="th1"><a name="secure" class="intable">Безопасность</a></th></tr>
Traceback (most recent call last):
File "./examles.py", line 16, in <module>
print unicode(str(tds), 'utf-8')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 233-239: ordinal not in range(128)
это если запусать из файла, а если запускать из консоли python то не работает вообще. Непонимаю проблема в beautifulsoup или в питоне.
PS Ubuntu 9.04



Отредактировано (Ноя. 21, 2009 13:18:23)

Офлайн

#8 Ноя. 21, 2009 13:29:48

andreykyz
От:
Зарегистрирован: 2009-11-19
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

Как я понял ошибка возникает при экспорте из beautifulsoup



Офлайн

#9 Ноя. 21, 2009 14:47:39

andreykyz
От:
Зарегистрирован: 2009-11-19
Сообщения: 18
Репутация: +  0  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

Еще не работает вот это :(

parser = html5lib.HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))
soup = parser.parse(open("catalog.htm"))
table_soup = soup.table.tbody.tr.td.table.tbody.tr.nextSibling.nextSibling.tbody
print soup.contents[0].name # не работает
Traceback (most recent call last):
File "./examles.py", line 15, in <module>
print soup.contents[0].name
File "/var/lib/python-support/python2.5/BeautifulSoup.py", line 427, in __getattr__
raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr)
AttributeError: 'Declaration' object has no attribute 'name'
причем soup.name - работает

Скажите хотябы какой версией python, html5lib и BeautifulSoup пользуетесь вы



Офлайн

#10 Ноя. 23, 2009 07:48:53

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

beautifulsoup + html5lib обход дерева циклом

andreykyz
AttributeError: ‘Declaration’ object has no attribute ‘name’
Опять же, если копнуть глубже в HTML и даже в ваш catalog.hm, то вы наверняка увидите в первой строчке что-то типа такого
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
Это объявление о типе вашего документа. Почитайте тут: http://www.w3schools.com/tags/tag_DOCTYPE.asp

Так вот, выражение
soup.contents[0]
возращает вам как раз это объявление завернутое в объект Declaration. А вот
soup.contents[0].nexSibling
как раз таки должен быть объект - Tag “html”



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version