1

我在 PyObjC 中为我的学习实现了一个最小的浏览器。首先,我在 pyobjc 中搜索了使用 webkit 的方法,并编写了如下代码:

#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 共享 cookie。我希望它独立于我的 Safari.app。所以我再次用谷歌搜索,我了解到我可以使用NSMutableURLRequest覆盖 cookie-handling-methods 。下面是我测试的第二个代码:

#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()

这段代码向我展示了 twitter 的登录屏幕 :-) 但我无法通过此浏览器登录 twitter。我输入帐户名、密码并按下回车键。然后浏览器会显示我一直在 Safari.app 中使用的帐户的时间线。

是的,我知道这是正确的结果。我没有写任何关于处理 cookie 的内容。我的问题是关于这一点。我想知道:

  1. 如何实现和使用类似NSHTTPCookieStorage 的东西?
  2. 我可以用python写吗?

谢谢你。

4

1 回答 1

0

从简单的部分开始:如果可以在 Objective-C 中执行此操作,那么 PyObjC 也应该可以。

也就是说,我不清楚这是否可能。如何在不共享 cookie 的情况下拥有多个 webkit 实例?似乎表明它不是,尽管您可以通过 webkit 委托做某事。

另一种选择是使用 NSURLProtocol,注册一个自定义 NSURLProtocol 类来处理 http/https 请求并使用 Python 的 urllib 或 urllib2 实现它。PyDocURL示例展示了如何执行此操作(该示例为 pydoc:// URL 注册了一个子类)。

有关 NSURLConnection 的更多信息,请访问 Apple 网站。

更新了实现提示:

另一种方法可能是通过 NSHTTPCookieStorage (NSHTTPCookieStorage.sharedHTTPCookieStorage.setCookieAcceptPolicy_(NSHTTPCookieAcceptPolicyNever)) 禁用 cookie 存储。然后使用 webkit 资源加载委托自己处理 cookie:

  • 维护自己的 cookie 存储(可能使用 urllib2 中的类)

  • 在 webView:resource:willSendRequest:redirectResponse:fromDataSource: 根据该存储中的信息添加 cookie 标头

  • 在 webView:resource:didReceiveResponse:fromDataSource: 检查“set-cookie”标头并更新您自己的 cookie 存储。

这样做应该不会太难,我很想在 PyObjC 网站上将此功能作为示例(或者甚至作为 PyObjC 的 WebKit 绑定中的实用程序类)。

于 2013-02-25T08:08:02.870 回答