Scrapy - 如何管理 Cookies/会话

62 投票
6 回答
61203 浏览
提问于 2025-04-16 11:43

我对Scrapy中的cookies是怎么工作的,以及如何管理这些cookies有点困惑。

我想做的事情可以简单描述成这样:

enter image description here

这个网站的工作方式:

当你访问这个网站时,你会得到一个会话cookie。

当你进行搜索时,网站会记住你搜索的内容,所以当你点击查看下一页结果时,它知道你在查找什么。


我的脚本:

我的爬虫的起始网址是searchpage_url。

这个搜索页面是通过parse()请求的,搜索表单的响应会传递给search_generator()

search_generator()会使用FormRequest和搜索表单的响应生成很多搜索请求。

每一个FormRequest,以及后续的子请求都需要有自己的会话,所以需要有自己的cookie jar和会话cookie。


我看到文档中有一部分提到meta选项,可以防止cookies被合并。这是什么意思呢?这是否意味着发起请求的爬虫在它的整个生命周期中都会有自己的cookie jar?

如果cookies是按爬虫级别管理的,那么当多个爬虫同时运行时,这个机制是怎么工作的呢?是否可以让只有第一个请求生成器生成新的爬虫,并确保从那时起只有那个爬虫处理后续请求?

我想我需要禁用多个并发请求……否则一个爬虫会在同一个会话cookie下进行多个搜索,而后续请求只会与最近的搜索相关?

我有点困惑,任何澄清都会非常感谢!


编辑:

我刚想到的另一个选项是完全手动管理会话cookie,并将其从一个请求传递到另一个请求。

我想这意味着要禁用cookies,然后从搜索响应中获取会话cookie,并将其传递给每个后续请求。

在这种情况下,这样做是对的吗?

6 个回答

2
def parse(self, response):
    # do something
    yield scrapy.Request(
        url= "http://new-page-to-parse.com/page/4/",
        cookies= {
            'h0':'blah',
            'taeyeon':'pretty'
        },
        callback= self.parse
    )

当然可以!请把你想要翻译的内容发给我,我会帮你把它变得更简单易懂。

7

在编程中,有时候我们需要让程序做一些事情,比如在特定的条件下执行某段代码。这个过程就像给程序下达命令,让它在满足某些条件时才去做某件事。

例如,你可能希望在用户输入正确的密码后,程序才允许他们进入系统。这就需要用到“条件语句”,它可以帮助我们判断条件是否成立,然后决定接下来要执行的操作。

条件语句就像是一个分岔路口,程序在这里会根据条件的真假选择不同的路径。这样,我们就能控制程序的行为,让它更智能地响应用户的操作。

总之,条件语句是编程中非常重要的工具,它让我们的程序能够根据不同的情况做出不同的反应。

from scrapy.http.cookies import CookieJar
...

class Spider(BaseSpider):
    def parse(self, response):
        '''Parse category page, extract subcategories links.'''

        hxs = HtmlXPathSelector(response)
        subcategories = hxs.select(".../@href")
        for subcategorySearchLink in subcategories:
            subcategorySearchLink = urlparse.urljoin(response.url, subcategorySearchLink)
            self.log('Found subcategory link: ' + subcategorySearchLink), log.DEBUG)
            yield Request(subcategorySearchLink, callback = self.extractItemLinks,
                          meta = {'dont_merge_cookies': True})
            '''Use dont_merge_cookies to force site generate new PHPSESSID cookie.
            This is needed because the site uses sessions to remember the search parameters.'''

    def extractItemLinks(self, response):
        '''Extract item links from subcategory page and go to next page.'''
        hxs = HtmlXPathSelector(response)
        for itemLink in hxs.select(".../a/@href"):
            itemLink = urlparse.urljoin(response.url, itemLink)
            print 'Requesting item page %s' % itemLink
            yield Request(...)

        nextPageLink = self.getFirst(".../@href", hxs)
        if nextPageLink:
            nextPageLink = urlparse.urljoin(response.url, nextPageLink)
            self.log('\nGoing to next search page: ' + nextPageLink + '\n', log.DEBUG)
            cookieJar = response.meta.setdefault('cookie_jar', CookieJar())
            cookieJar.extract_cookies(response, response.request)
            request = Request(nextPageLink, callback = self.extractItemLinks,
                          meta = {'dont_merge_cookies': True, 'cookie_jar': cookieJar})
            cookieJar.add_cookie_header(request) # apply Set-Cookie ourselves
            yield request
        else:
            self.log('Whole subcategory scraped.', log.DEBUG)
55

三年后,我觉得这正是你所寻找的内容:

http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#std:reqmeta-cookiejar

在你的爬虫的开始请求方法中,可以使用类似这样的代码:

for i, url in enumerate(urls):
    yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
        callback=self.parse_page)

记得,对于后续的请求,你需要每次都明确地重新附加cookiejar:

def parse_page(self, response):
    # do some processing
    return scrapy.Request("http://www.example.com/otherpage",
        meta={'cookiejar': response.meta['cookiejar']},
        callback=self.parse_other_page)

撰写回答