【问题标题】:How to send cookie with scrapy CrawlSpider requests?如何使用抓取的 CrawlSpider 请求发送 cookie?
【发布时间】:2015-12-13 21:46:01
【问题描述】:

我正在尝试使用 Python 的 Scrapy 框架创建这个 Reddit scraper

我使用 CrawSpider 爬过 Reddit 及其子版块。但是,当我遇到包含成人内容的网页时,该网站会要求提供 cookie over18=1

所以,我一直在尝试在蜘蛛发出的每个请求中发送一个 cookie,但是,它没有成功。

这是我的蜘蛛代码。如您所见,我尝试使用start_requests() 方法为每个蜘蛛请求添加一个cookie。

这里有人能告诉我怎么做吗?还是我做错了什么?

from scrapy import Spider
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from reddit.items import RedditItem
from scrapy.http import Request, FormRequest

class MySpider(CrawlSpider):
    name = 'redditscraper'
    allowed_domains = ['reddit.com', 'imgur.com']
    start_urls = ['https://www.reddit.com/r/nsfw']

    rules = (
        Rule(LinkExtractor(
            allow=['/r/nsfw/\?count=\d*&after=\w*']),
            callback='parse_item',
            follow=True),
    )

    def start_requests(self):
        for i,url in enumerate(self.start_urls):
            print(url)
            yield Request(url,cookies={'over18':'1'},callback=self.parse_item)

    def parse_item(self, response):
        titleList = response.css('a.title')

        for title in titleList:
            item = RedditItem()
            item['url'] = title.xpath('@href').extract()
            item['title'] = title.xpath('text()').extract()
            yield item

【问题讨论】:

  • cookie在request.cookies中吗?
  • @esfy 不,我猜。我在Request(url,cookies={'over18':'1'},callback=self.parse_item) 中指定了cookie

标签: python cookies web-scraping scrapy


【解决方案1】:

我找到了 CrawlSpider 的解决方案:

def start_requests(self):
    yield Request(url=self.start_urls[0], callback=self._parse, cookies={'beget': 'begetok'})

【讨论】:

    【解决方案2】:

    您可以在规则中使用 process_request 参数,例如:

        rules = (
        Rule(LinkExtractor(
            allow=['/r/nsfw/\?count=\d*&after=\w*']),
            callback='parse_item',
            process_request='ammend_req_header',
            follow=True)
    
        def ammend_req_header(self, request):
            request.cookies['over18']=1
            return request
    

    【讨论】:

      【解决方案3】:

      The Scrapy Docs

      1.使用字典:

      request_with_cookies = Request(url="http://www.example.com",
                                     cookies={'currency': 'USD', 'country': 'UY'})
      

      2.使用字典列表:

      request_with_cookies = Request(url="http://www.example.com",
                                     cookies=[{'name': 'currency',
                                              'value': 'USD',
                                              'domain': 'example.com',
                                              'path': '/currency'}])
      

      【讨论】:

        【解决方案4】:

        你也可以通过header发送。

        scrapy.Request(url=url, callback=callback, headers={'Cookie':my_cookie})
        

        【讨论】:

          【解决方案5】:

          好的。尝试做这样的事情。

          def start_requests(self):
              headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36'}
              for i,url in enumerate(self.start_urls):
                  yield Request(url,cookies={'over18':'1'}, callback=self.parse_item, headers=headers)
          

          是用户代理阻止了你。

          编辑:

          不知道CrawlSpider 有什么问题,但Spider 无论如何都可以工作。

          #!/usr/bin/env python
          # encoding: utf-8
          import scrapy
          
          
          class MySpider(scrapy.Spider):
              name = 'redditscraper'
              allowed_domains = ['reddit.com', 'imgur.com']
              start_urls = ['https://www.reddit.com/r/nsfw']
          
              def request(self, url, callback):
                  """
                   wrapper for scrapy.request
                  """
                  request = scrapy.Request(url=url, callback=callback)
                  request.cookies['over18'] = 1
                  request.headers['User-Agent'] = (
                      'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, '
                      'like Gecko) Chrome/45.0.2454.85 Safari/537.36')
                  return request
          
              def start_requests(self):
                  for i, url in enumerate(self.start_urls):
                      yield self.request(url, self.parse_item)
          
              def parse_item(self, response):
                  titleList = response.css('a.title')
          
                  for title in titleList:
                      item = {}
                      item['url'] = title.xpath('@href').extract()
                      item['title'] = title.xpath('text()').extract()
                      yield item
                  url = response.xpath('//a[@rel="nofollow next"]/@href').extract_first()
                  if url:
                      yield self.request(url, self.parse_item)
                  # you may consider scrapy.pipelines.images.ImagesPipeline :D
          

          【讨论】:

          • 成功了。但在我接受你的回答之前,我认为 cookie 仅适用于第一个请求,它不适用于分页请求。即它仅适用于start_urls,但不适用于我们从LinkExtractor获得的分页网址
          • 其实问题是别的,我用start_requests()方法,爬到一页就停止了。但是我将其删除,它开始爬行分页。想知道为什么!
          • 噢,客户端设置的cookie不会像服务器发送的那样在请求之间保留自己。也许cookiejar 可以。
          • 它的工作。伟大的。谢谢您的帮助。没有意识到您发布了编辑。有趣的是我没有收到任何通知。无论如何,必须对CrawlSpider 有什么问题进行一些研究
          猜你喜欢
          • 2020-01-24
          • 2014-12-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-31
          • 2016-01-25
          • 1970-01-01
          相关资源
          最近更新 更多