Найти - Пользователи
Полная версия: grab и кодировка ответа
Начало » Data Mining » grab и кодировка ответа
1
Alex_HH
Здравствуйте!
Проблема небольшая, помогите пожалуйста.
Имеем: питон 3 и граб 0.4.13

Пишем:
from grab import Grab
g = Grab()
g.go ('www.f1news.ru')
print(g.doc.select('//title').text())
Получаем:
1 F1news.ru - 2014 1
Должны получить:
Формула 1 на F1news.ru - новости чемпионата 2014 Формулы 1

Ну как бы граб должен автоматом определять кодировку, о чем нам и говорит документация

Но эта же документация нам говорит что может и не определить, не вопрос - мы не гордые. Идем в файербаг и смотрим что нам надо, а надо нам это:
<meta content="text/html; charset=windows-1251" http-equiv="Content-Type">

После чего возвращаемся в редактор кода и пишем слудующее:
from grab import Grab
g = Grab()
g.setup(charset = 'windows-1251')
g.go ('www.f1news.ru')
print(g.doc.select('//title').text())

В итоге получаем тоже что и в первом случае. Поробовал зайти на др сайты с такой же кодировкой, проблема не исчезла.
Что я делаю не так, подскажите.
Спасибо за ответы.

PS В порыве гнева перепробовал следующее:
g.setup(charset = 'Windows-1251')
g.setup(charset = 'WINDOWS-1251')
g.setup(charset = 'windows - 1251')
g.setup(charset = 'cp1251')
g.setup(charset = 'CP1251')
Ничего не помогло.
AleksRevo
Смотрим
сюда: https://github.com/lorien/grab/blob/master/grab/base.py#L235
сюда: https://github.com/lorien/grab/blob/master/grab/base.py#L587
и сюда: https://github.com/lorien/grab/blob/master/grab/document.py#L522
и, наверно, постим баг.
Alex_HH
AleksRevo
Смотрим сюда: https://github.com/lorien/grab/blob/master/grab/base.py#L235сюда: https://github.com/lorien/grab/blob/master/grab/base.py#L587и сюда: https://github.com/lorien/grab/blob/master/grab/document.py#L522и, наверно, постим баг.

хм, вот так рабоатет:
from grab import Grab
g = Grab()
# ===!!!! ===
g.setup(document_charset = 'windows-1251')
# ===!!!! ===
g.go ('www.f1news.ru')
print(g.doc.select('//title').text())

я поннимаю в чем суть проблемы, но объяснить не могу, объясните пожалста мне и всем читателям суть.
и куда запостить баг?

PS большое спасибо

===Update ===
А в спайдере не работает.
AleksRevo
Вообще, у меня оно отваливалось чуть раньше с вот таким вот сообщением:

>>> g.go ('www.f1news.ru')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd4 in position 192: invalid continuation byte

И плевать ему было на явное указание кодировки, почему я полез в исходники, версии у нас вроде как одинаковые:

>>> grab.__version__
'0.4.13'

Возможно python разный

Python 3.3.5 (default, Sep 30 2014, 02:25:20) 
[GCC 4.7.3] on linux

В исходниках есть такой момент, стоило про него сразу написать, но я как-то увлёкся, что не все параметры передаются:
https://github.com/lorien/grab/blob/master/grab/base.py#L154

# Character set to which any unicode data should be encoded
# before get placed in request
# This setting is overwritten after each request with
# charset of retrieved document
charset='utf-8',
# Charset to use for converting content of response
# into unicode, by default it is detected automatically
document_charset=None,

charset - это во что перекодировать перед отправкой запроса.
document_charset - это из чего перекодировать, при парсинге документа.

И вот ещё: https://github.com/lorien/grab/issues/54

Если пишется полноценный бот взаимодействующий с сайтом, то наверно charset тоже может пригодиться устанавливать, хотя он должен устанавливаться автоматически по итогам предыдущих запросов.

В общем, Вам баг нет смысла постить, у Вас он просто не воспроизводится. А мне ещё стоит покопаться из-за чего он у меня при этом всё-таки проявляется. Хотя, судя по исходникам вроде всё очевидно: параметр не передаётся, задействуется только автоопределение исходной кодировки и оно не отрабатывает, сваливаясь в utf-8, на что намекает и ошибка.
Alex_HH
Спасибо, с этим вроде понял.
Моя версия питона:
Python 3.2.3 (default, Feb 20 2013, 17:02:41) 
[GCC 4.7.2] on linux2
А граб да, дейсвительно такой же.

Только мне теперь не совсем ясно как натсройть граб для спайдера.
Если делаю так, то оно работает, но мне кажеться это как то не красиво:
class f1news (Spider):
    initial_urls = ['http://www.f1news.ru/']
    base_url = 'http://www.f1news.ru/'
    def task_initial (self, grab, task):
        print ('Start')
        yestarday = grab.doc.select('//div[@id="lastNews"]/h3/span[@class="floatRight"]/a[2]/@href').text()
        # === !!!! ===
        g = Grab()
        g.setup(document_charset = 'windows-1251', url = yestarday)
        yield (Task('title', grab = g))
        # === !!!! ===

Мне кажеться это портит всю прелесть спайдера, да и натсроить один раз граб с самого начала, было бы логичнее, ведь для одного парсинга как правило нужны одни и теже настойки.

==== UPDATE ====
Таки залез в исходники и нашел следующее:
def prepare(self):
        """
        You can do additional spider customizatin here
        before it has started working. Simply redefine
        this method in your Spider class.
        """

Правда этот фрагмент кода есть в примерах из документации, там где парситься хабр, это я чуть чуть проморгал.

И второе что нашел:
def setup_grab(self, **kwargs):
        self.grab_config.update(**kwargs)

Этого в документации я не нашел.
И теперь настройка граба выглядит так:
class f1news (Spider):
    initial_urls = ['http://www.f1news.ru/']
    base_url = 'http://www.f1news.ru/'
    
    # ==== !!!! ====
    def prepare(self):
        self.setup_grab(document_charset = 'windows-1251')
    # ==== !!!! ====
    
    def task_initial (self, grab, task):
        print ('Start')
        yestarday = grab.doc.select('//div[@id="lastNews"]/h3/span[@class="floatRight"]/a[2]/@href').text()
        yield (Task('title', url = yestarday))

Вроде пока все.
William888
неграмотно написал… вместо “c Python-интерфейсом” - следует читать “(grab или что-то другое легко устанавливаемое под Python 2.7)”70-486 - исправляю…
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB