Je travaille sur un projet de classe et j'essaie d'obtenir toutes les données de film IMDB (titres, budgets, etc.) jusqu'en 2016. J'ai adopté le code de https://github.com/alexwhb/IMDB-spider/blob/master/tutorial/spiders/spider.py.

Ma pensée est: de i dans la plage (1874,2016) (depuis 1874 est la première année indiquée sur http: // www.imdb.com/year/), dirigez le programme vers le site Web de l'année correspondante et récupérez les données de cette URL.

Mais le problème est que chaque page de chaque année n'affiche que 50 films, donc après avoir exploré les 50 films, comment passer à la page suivante? Et après avoir rampé chaque année, comment puis-je passer à l'année prochaine? C'est mon code pour la partie d'url d'analyse jusqu'à présent, mais il ne peut explorer que 50 films pour une année particulière.

class tutorialSpider(scrapy.Spider):
    name = "tutorial"
    allowed_domains = ["imdb.com"]
    start_urls = ["http://www.imdb.com/search/title?year=2014,2014&title_type=feature&sort=moviemeter,asc"] 

    def parse(self, response):
            for sel in response.xpath("//*[@class='results']/tr/td[3]"):
                item = MovieItem()
                item['Title'] = sel.xpath('a/text()').extract()[0]
                item['MianPageUrl']= "http://imdb.com"+sel.xpath('a/@href').extract()[0]
                request = scrapy.Request(item['MianPageUrl'], callback=self.parseMovieDetails)
                request.meta['item'] = item
                yield request
0
Chiefscreation 5 mars 2016 à 23:20

4 réponses

Meilleure réponse

Vous pouvez utiliser CrawlSpiders pour simplifier votre tâche. Comme vous le verrez ci-dessous, start_requests génère dynamiquement la liste des URL tandis que parse_page extrait uniquement les films à explorer. La recherche et le suivi du lien 'Suivant' sont effectués par l'attribut rules.

Je suis d'accord avec @Padraic Cunningham que les valeurs de codage en dur ne sont pas une bonne idée. J'ai ajouté des arguments d'araignée pour que vous puissiez appeler: scrapy crawl imdb -a start=1950 -a end=1980 (le grattoir sera par défaut 1874-2016 s'il n'obtient aucun argument).

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

from imdbyear.items import MovieItem

class IMDBSpider(CrawlSpider):
    name = 'imdb'
    rules = (
        # extract links at the bottom of the page. note that there are 'Prev' and 'Next'
        # links, so a bit of additional filtering is needed
        Rule(LinkExtractor(restrict_xpaths=('//*[@id="right"]/span/a')),
            process_links=lambda links: filter(lambda l: 'Next' in l.text, links),
            callback='parse_page',
            follow=True),
    )

    def __init__(self, start=None, end=None, *args, **kwargs):
      super(IMDBSpider, self).__init__(*args, **kwargs)
      self.start_year = int(start) if start else 1874
      self.end_year = int(end) if end else 2016

    # generate start_urls dynamically
    def start_requests(self):
        for year in range(self.start_year, self.end_year+1):
            yield scrapy.Request('http://www.imdb.com/search/title?year=%d,%d&title_type=feature&sort=moviemeter,asc' % (year, year))

    def parse_page(self, response):
        for sel in response.xpath("//*[@class='results']/tr/td[3]"):
            item = MovieItem()
            item['Title'] = sel.xpath('a/text()').extract()[0]
            # note -- you had 'MianPageUrl' as your scrapy field name. I would recommend fixing this typo
            # (you will need to change it in items.py as well)
            item['MainPageUrl']= "http://imdb.com"+sel.xpath('a/@href').extract()[0]
            request = scrapy.Request(item['MainPageUrl'], callback=self.parseMovieDetails)
            request.meta['item'] = item
            yield request
    # make sure that the dynamically generated start_urls are parsed as well
    parse_start_url = parse_page

    # do your magic
    def parseMovieDetails(self, response):
        pass
2
Greg Sadetsky 7 mars 2016 à 00:48

Le code fourni par @Greg Sadetsky nécessite quelques modifications mineures. Eh bien un seul changement qui est dans la première ligne de la méthode parse_page.

    Just change xpath in the for loop from:
    response.xpath("//*[@class='results']/tr/td[3]"):
    to
    response.xpath("//*[contains(@class,'lister-item-content')]/h3"):

Cela a fonctionné comme un charme pour moi!

0
Ejaz Shaikh 23 avril 2019 à 16:08

J'ai trouvé un moyen très stupide de résoudre ce problème. J'ai mis tous les liens dans les start_urls. Une meilleure solution serait très appréciée!

class tutorialSpider(scrapy.Spider):
    name = "tutorial"
    allowed_domains = ["imdb.com"]
    start_urls = []
    for i in xrange(1874, 2017):
        for j in xrange(1, 11501, 50): 
        # since the largest number of movies for a year to have is 11,400 (2016)
        start_url = "http://www.imdb.com/search/title?sort=moviemeter,asc&start=" + str(j) + "&title_type=feature&year=" + str(i) + "," + str(i)
        start_urls.append(start_url)

    def parse(self, response):
        for sel in response.xpath("//*[@class='results']/tr/td[3]"):
            item = MovieItem()
            item['Title'] = sel.xpath('a/text()').extract()[0]
            item['MianPageUrl']= "http://imdb.com"+sel.xpath('a/@href').extract()[0]
            request = scrapy.Request(item['MianPageUrl'], callback=self.parseMovieDetails)
            request.meta['item'] = item
            yield request
0
Chiefscreation 5 mars 2016 à 21:17
you can use the below piece of code to follow the next page
#'a.lister-page-next.next-page::attr(href)' is the selector to get the next page link

next_page = response.css('a.lister-page-next.nextpage::attr(href)').extract_first() # joins current and next page url
if next_page is not None:
           next_page = response.urljoin(next_page)
           yield scrapy.Request(next_page, callback=self.parse) # calls parse function again when crawled to next page

1
Vivek Shakya 2 août 2017 à 11:58