Как самостоятельно обрабатывать файлы cookie в PyObjC

Я реализую минимальный браузер в PyObjC для своего исследования. Сначала я погуглил, как использовать webkit от pyobjc, и написал код, как показано ниже:

#coding: utf-8

import Foundation
import WebKit
import AppKit
import objc

def main():
    app = AppKit.NSApplication.sharedApplication()
    rect = Foundation.NSMakeRect(100,350,600,800)
    win = AppKit.NSWindow.alloc()
    win.initWithContentRect_styleMask_backing_defer_(
        rect,
        AppKit.NSTitledWindowMask |
            AppKit.NSClosableWindowMask |
            AppKit.NSResizableWindowMask |
            AppKit.NSMiniaturizableWindowMask,
        AppKit.NSBackingStoreBuffered,
        False)
    win.display()
    win.orderFrontRegardless()

    webview = WebKit.WebView.alloc()
    webview.initWithFrame_(rect)

    pageurl = Foundation.NSURL.URLWithString_("http://twitter.com")
    req = Foundation.NSURLRequest.requestWithURL_(pageurl)
    webview.mainFrame().loadRequest_(req)

    win.setContentView_(webview)
    app.run()

if __name__ == '__main__':
    main()

Это работало нормально. Но я заметил, что этот браузер делится куки с сафари. Я хочу, чтобы он не зависел от моего Safari.app. Поэтому я снова погуглил и узнал, что могу переопределить методы обработки файлов cookie с помощью NSMutableURLRequest. Ниже приведен второй код, который я тестировал:

#coding: utf-8

import Foundation
import WebKit
import AppKit
import objc

def main():
    app = AppKit.NSApplication.sharedApplication()
    rect = Foundation.NSMakeRect(100,350,600,800)
    win = AppKit.NSWindow.alloc()
    win.initWithContentRect_styleMask_backing_defer_(
        rect,
        AppKit.NSTitledWindowMask |
            AppKit.NSClosableWindowMask |
            AppKit.NSResizableWindowMask |
            AppKit.NSMiniaturizableWindowMask,
        AppKit.NSBackingStoreBuffered,
        False)
    win.display()
    win.orderFrontRegardless()

    webview = WebKit.WebView.alloc()
    webview.initWithFrame_(rect)

    pageurl = Foundation.NSURL.URLWithString_("http://twitter.com")
    req = Foundation.NSMutableURLRequest.requestWithURL_(pageurl)
    Foundation.NSMutableURLRequest.setHTTPShouldHandleCookies_(req, False)
    webview.mainFrame().loadRequest_(req)

    win.setContentView_(webview)
    app.run()

if __name__ == '__main__':
    main()

Этот код показывает мне экран входа в твиттер :-) Но я не смог войти в твиттер с помощью этого браузера. Я ввожу имя учетной записи, пароль и нажимаю клавишу ввода. Затем браузер отображает временную шкалу учетной записи, которую я всегда использую в Safari.app.

Да, я знаю, что это правильный результат. Я ничего не писал об обработке файлов cookie. И мой вопрос по этому поводу. Я хочу знать, что:

  1. Как я могу реализовать и использовать что-то вроде NSHTTPCookieStorage?
  2. Могу ли я написать это на питоне?

Спасибо.


person user2100702    schedule 22.02.2013    source источник


Ответы (1)


Начнем с простой части: если это возможно сделать в Objective-C, то это должно быть возможно и с PyObjC.

Тем не менее, мне неясно, возможно ли это вообще. Как я могу иметь несколько экземпляров webkit без совместного использования cookies?, кажется, указывает на то, что это не так, хотя вы можете что-то сделать с помощью делегата webkit.

Другой альтернативой является использование NSURLProtocol, регистрация пользовательского класса NSURLProtocol для обработки запросов http/https и реализация этого с помощью Python urllib или urllib2. В примере PyDocURL показано, как это сделать (в этом примере регистрируется подкласс для URL-адресов pydoc://).

Дополнительная информация о NSURLConnection находится на веб-сайте Apple.

Обновлено с подсказкой реализации:

Альтернативным методом может быть отключение хранилища файлов cookie с помощью NSHTTPCookieStorage (NSHTTPCookieStorage.sharedHTTPookieStorage.setCookieAcceptPolicy_(NSHTTPCookieAcceptPolicyNever)). Затем используйте делегат загрузки ресурсов webkit для самостоятельной обработки файлов cookie:

  • Поддерживайте собственное хранилище файлов cookie (возможно, используя класс в urllib2)

  • В webView:resource:willSendRequest:redirectResponse:fromDataSource: добавьте заголовки файлов cookie на основе информации в этом хранилище.

  • В webView:resource:didReceiveResponse:fromDataSource: проверьте заголовки «set-cookie» и обновите собственное хранилище файлов cookie.

Это не должно быть слишком сложно сделать, и я хотел бы иметь эту функциональность в качестве примера на веб-сайте PyObjC (или даже в качестве служебного класса в привязках WebKit для PyObjC).

person Ronald Oussoren    schedule 25.02.2013
comment
Во-первых, спасибо за ваш ответ. Я знаю, что есть некоторые браузеры, реализованные в Obj-C/Cocoa, и у них есть собственные файлы cookie. А вчера я нашел статью в блоге, в которой он объяснил, как реализовать управление файлами cookie, которые отошли от Safari.app. Но я не могу найти, как это сделать в pyobjc. Я должен больше узнать об основах Cocoa и PyObjC. - person user2100702; 25.02.2013
comment
Не могли бы вы опубликовать ссылку на эту статью в блоге, я мог бы помочь (кстати, я автор PyObjC). - person Ronald Oussoren; 25.02.2013
comment
В этой статье рассказывается об обработке файлов cookie. Там написано, что - (NSURLRequest *)webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource ; и - (void)webView:(WebView *)sender resource:(id)identifier didReceiveResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)dataSource ; это ключ. - person user2100702; 25.02.2013
comment
Я не могу прочитать эту статью, но это, вероятно, отвлекающий маневр. Вероятно, он говорит то же самое, что и вопрос StackOverlow, на который я ссылался ранее: вы можете сделать это с помощью методов, которые вы упомянули, но это будет много работы. - person Ronald Oussoren; 26.02.2013
comment
Я с тобой согласен. Это может быть слишком сложно для моего мастерства. Я сделаю это в качестве долгосрочного домашнего задания. Большое спасибо! - person user2100702; 26.02.2013