Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет schegloff ([info]schegloff)
@ 2007-04-05 23:17:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Спасибо всем, или Чтение подзамочных записей ЖЖ из python
Полторы недели назад я обратился к ALL'у с просьбой о помощи - "Помогите решить проблему с авторизацией на livejournal.com". Так вот, мне реально помогли!

Основную поддержку оказал LJR-юзер do_, подсказавший мне, что "LJ вместо того, чтобы сразу присылать документ, любит от души поперенаправлять на другой адрес..." - это нормальное поведение LJ, а не изысканный способ посылания меня подальше. После этого моральная поддержка [info]neo_der_tall@lj в Клубе упала на подготовленную почву - и вот за два вечера задача оказалась решена. Теперь у меня есть альфа-версия lj_archiver.py, читающая подзамочные записи.

На всякий случай, приведу свой способ решения задачи авторизации в ЖЖ (не-питонщикам под катом будет неинтересно):


import httplib, urllib
def str_between( s, ps1, ps2 ) :
    pos1 = s.find(ps1)
    pos2 = s.find(ps2, pos1+len(ps1))
    if pos1>-1 and pos2>-1 and pos2>pos1 :
        return s[pos1+len(ps1):pos2]
    else :
        return ""

def read_safe_post( c_url, c_user, c_pass ) :
    c_data = urllib.urlencode( {"mode":"login", "user":c_user, "password":c_pass} )
    c_data_l = len(c_data)
    # 1. Регистрируемся на LJ и получаем базовые куки
    # theurl = "http://www.livejournal.com/login.bml?ret=1"
    host = "www.livejournal.com"
    tail = "/login.bml?ret=1"
    lj_conn = httplib.HTTPConnection(host) 
    lj_conn.connect()
    lj_conn.putrequest("POST", tail)
    lj_conn.putheader("Content-Type", "application/x-www-form-urlencoded")
    lj_conn.putheader("Content-Length", str(c_data_l))
    lj_conn.endheaders()
    lj_conn.send(c_data)
    r = lj_conn.getresponse()
    r_cookie = r.msg.getheader("Set-Cookie")
    # Сами данные не читаем - нам нужны только куки
    lj_conn.close()

    # Приводим полученные куки к удобоваримому виду
    c_ljuniq = str_between(r_cookie, "ljuniq=", ";")
    c_ljlogg = str_between(r_cookie, "ljloggedin=", ";")
    c_ljsess = str_between(r_cookie, "ljsession=", ";")
    c_ljmass = str_between(r_cookie, "ljmastersession=", ";")
    if len(c_ljuniq)==0 or len(c_ljlogg)==0 or len(c_ljsess)==0 or len(c_ljmass)==0 :
        print "Bad cookie..."
    else :
        print "Cookie OK!"
    c_cookie = "ljuniq=" + c_ljuniq + "; ljloggedin=" + c_ljlogg \
           + "; ljsession=" + c_ljsess + "; ljmastersession=" + c_ljmass

    # 2. Обрабатываем цепочку редиректов до получения
    # СПЕЦИАЛИЗИРОВАННОЙ куки для url, который нужно прочитать
    # Хитрость в том, что для каждого url - свой ljdomsess,
    # и получить его можно только (?) пройдя по цепочке
    theurl = c_url
    for i in range(5) :  # Обычно за 5 циклов коннектится, чистая эмпирика
        print theurl
        p1 = theurl.find("//")
        p2 = theurl.find("/",p1+2)
        host = theurl[p1+2:p2]
        tail = theurl[p2:]
        lj_conn = httplib.HTTPConnection(host) 
        lj_conn.connect()
        lj_conn.putrequest("GET", tail)
        lj_conn.putheader("Cookie",c_cookie)
        lj_conn.endheaders()
        r = lj_conn.getresponse()
        if r.status == 200 :
            s_res = r.read()
            lj_conn.close()
            break
        if r.status == 302 :
            r_cookie = r.msg.getheader("Set-Cookie","")
            if len(r_cookie)>0 :
                # ищем специализированную куку - 
                c_ljspec = str_between(r_cookie, "ljdomsess",";")
                c_cookie = c_cookie + "; ljdomsess"+c_ljspec
            theurl = r.msg.getheader("Location")
        lj_conn.close()
    return s_res

# Вызов процедуры:
# s = read_safe_post(url, user, password)
# где все переменные - обычные строки


Разумеется, это только самая первая версия авторизатора, которую еще дорабатывать и дорабатывать (например, нет смысла авторизироваться при каждом запросе ЖЖ-url, достаточно сделать это один раз и сохранить базовые куки, редиректы с 302-м сообщением возникают не для каждого url, некоторые открываются сразу по базовым кукам, и т.д.). Но поскольку я в Сети ничего подобного не видел, размещаю текст как пример - как это делается.

Еще раз всем спасибо!