Question

Problem

I'm trying to crawl a site like YouTube that has a list with a bunch of videos and a link to the individual video. What I'm trying to do is grab the thumbnail image of the video before going into the specific video with parse_item().

The problem is I have no idea how to bring the Response object of the "list view" into the parse_item() function. I know you can intercept the request with process_request and insert a meta to the Request object, but I can't figure out how to get the list view Response.

Is there a different approach to this problem?

My code:

import re
import datetime

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.selector import Selector
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor

from ..items import ExampleItem


class ExampleSpider(CrawlSpider):
    """
    Crawler for: www.example.com
    """

    name = "example"

    allowed_domains = ['www.example.com']

    start_urls = ['http://www.example.com']

    rules = (
        Rule(SgmlLinkExtractor(
            restrict_xpaths=["//div[@class='pagination']"]
        )),

        Rule(SgmlLinkExtractor(
            restrict_xpaths=["//ul[@class='list']"],
            deny=['/user/'],
        ), callback='parse_item', process_request='parent_url')
    )

    def parent_url(self, request):

        request.meta['parent_page'] = '' #  Get the parent response somehow?
        return request

    def parse_item(self, response):

        sel = Selector(response)

        item = ExampleItem()

        duration = sel.css('.video span::text')[0].extract()

        item['title'] = sel.css('.title::text')[0].extract()
        item['description'] = sel.xpath('//div[@class="description"]/text()').extract()
        item['duration'] = self._parse_duration(duration)
        item['link'] = response.url

        return item

    def _parse_duration(self, string):
        """
        Parse the duration field for times
        return Datetime object
        """

        if len(string) > 20:
            return datetime.datetime.strptime(string, '%H hours %M min %S sec').time()

        if '60 min' in string:
            string.replace('60 min', '01 hours 00 min')
            return datetime.datetime.strptime(string, '%H hours %M min %S sec')

        return datetime.datetime.strptime(string, '%M min %S sec').time()
Était-ce utile?

La solution

I'm assuming you want to know the URL from where a link (request) was extracted from.

You can override the method _requests_to_follow in order to pass around the source page of the request:

    def _requests_to_follow(self, response):
        for req in super(ExampleSpider, self)._requests_to_follow(response):
            req.meta['parent_page'] = response.url
            yield req
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top