Scrapy通过完整的webkit javascript执行来管理会话cookie

时间:2014-03-01 19:56:59

标签: python session cookies webkit scrapy

我正在尝试使用scrapy来抓取一个广泛使用javascript来操作文档,cookie等的网站(但没有像JSON响应那样简单)。出于某种原因,我无法从网络流量中确定,我需要的页面在我刮擦时出现错误,但在浏览器中查看时则不然。所以我想要做的是使用webkit来呈现浏览器中显示的页面,然后抓取它。 scrapyjs项目是为此目的而制作的。

要访问我需要的页面,我必须先登录,并保存一些会话cookie。我的问题是,当它呈现页面时,我无法成功地向webkit提供会话cookie。我有两种方法可以做到这一点:

  1. 专门使用scrapy页面请求,直到我到达需要webkit的页面,然后传递必要的cookie。
  2. 在scrapy中使用webkit(通过修改版本的scrapyjs),从登录到我到达我需要的页面的整个会话,并允许它根据需要保留cookie。
  3. 不幸的是,这两种方法似乎都没有用。

    按照方法1的说法,我尝试了以下方法: 在settings.py -

    DOWNLOADER_MIDDLEWARES = {
        'scrapyjs.middleware.WebkitDownloader': 701, #to run after CookiesMiddleware
    }
    

    我修改了scrapyjs来发送cookie:scrapyjs / middleware.py -

    import gtk
    import webkit
    import jswebkit
    #import gi.repository import Soup  # conflicting static and dynamic includes!?
    import ctypes
    libsoup = ctypes.CDLL('/usr/lib/i386-linux-gnu/libsoup-2.4.so.1')
    libwebkit = ctypes.CDLL('/usr/lib/libwebkitgtk-1.0.so.0')
    
    def process_request( self, request, spider ):
        if 'renderjs' in request.meta:
            cookies = request.headers.getlist('Cookie')
            if len(cookies)>0:
                cookies = cookies[0].split('; ')
                cookiejar = libsoup.soup_cookie_jar_new()
                libsoup.soup_cookie_jar_set_accept_policy(cookiejar,0) #0==ALWAYS ACCEPT
                up = urlparse(request.url)
                for c in cookies:
                    sp=c.find('=') # find FIRST = as split position
                    cookiename = c[0:sp]; cookieval = c[sp+1:];
                    libsoup.soup_cookie_jar_add_cookie(cookiejar, libsoup.soup_cookie_new(cookiename,cookieval,up.hostname,'None',-1))
                    session = libwebkit.webkit_get_default_session()
                    libsoup.soup_session_add_feature(session,cookiejar)
    
            webview = self._get_webview()
            webview.connect('load-finished', self.stop_gtk)
            webview.load_uri(request.url)
            ...
    

    设置cookiejar的代码改编自this response。问题可能在于进口的运作方式;也许这不是我正在修改的正确的webkit - 我不太熟悉webkit并且python文档很差。 (我不能使用from gi.repository import Soup的第二个答案的方法,因为它混合了静态库和动态库。我也找不到上面导入的webkit中的任何get_default_session()。

    第二种方法失败,因为会话不是跨请求保留的,而且我对webkit知之甚少知道如何使其在此框架中保持不变。

    任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:0)

实际上,第一种方法确实有效,但只进行了一次修改。 Cookie的路径必须是'/'(至少在我的应用程序中),而不是上面代码中的'None'。即,该行应

libsoup.soup_cookie_jar_add_cookie(cookiejar, libsoup.soup_cookie_new(cookiename,cookieval,up.hostname,'/',-1))

不幸的是,这只会稍微推回一下这个问题。现在cookie已正确保存,但整页(包括框架)仍然没有像我预期的那样使用webkit加载和呈现,因此DOM在浏览器中看不到它是完整的。如果我只是请求我想要的帧,那么我会得到错误页面而不是真实浏览器中显示的内容。我很想看看如何使用webkit渲染整个页面,包括框架。或者如何实现第二种方法,在webkit中完成整个会话。

答案 1 :(得分:0)

不知道Ithe应用程序的完整工作流程,您需要确保在webkit完成任何其他网络活动之前设置cookie jar。 http://webkitgtk.org/reference/webkitgtk/unstable/webkitgtk-Global-functions.html#webkit-get-default-session。根据我的经验,这实际上意味着甚至在实例化Web视图之前。

要检查的另一件事是您的框架是否来自同一个域.Cookie策略不允许跨不同域的Cookie。

最后,您可以注入Cookie。请参阅http://webkitgtk.org/reference/webkitgtk/unstable/webkitgtk-webkitwebview.html#WebKitWebView-navigation-policy-decision-requested或资源请求启动,然后在实际的汤消息上设置cookie。