我正在尝试使用scrapy来抓取一个广泛使用javascript来操作文档,cookie等的网站(但没有像JSON响应那样简单)。出于某种原因,我无法从网络流量中确定,我需要的页面在我刮擦时出现错误,但在浏览器中查看时则不然。所以我想要做的是使用webkit来呈现浏览器中显示的页面,然后抓取它。 scrapyjs项目是为此目的而制作的。
要访问我需要的页面,我必须先登录,并保存一些会话cookie。我的问题是,当它呈现页面时,我无法成功地向webkit提供会话cookie。我有两种方法可以做到这一点:
不幸的是,这两种方法似乎都没有用。
按照方法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知之甚少知道如何使其在此框架中保持不变。
任何帮助表示赞赏!
答案 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。