2015-04-23 4 views
1

Этот код обрывает IMDb сайт (получает названия фильмов, годы, звания и т. Д.) С выражениями XPath и возвращает их результат, но его функция selector() работает только правильно, а затем разрывается. Как это исправить?Почему эта функция работает правильно только один раз, а затем возвращает пустой список?

#!/usr/bin/env python3 
import lxml.html 
import requests as rq 


IMDB_HTML = "http://www.imdb.com/filmosearch" 
IMDB_JSON = "http://www.imdb.com/xml/find" 


class IMDBParser(object): 
    def __init__(self, role_type=None, sort_type='user_rating, desc', 
       job_type="actor", title_type="movie"): 
     self.job_type = job_type 
     self.sort_type = sort_type 
     self.title_type = title_type 
     self.role_type = role_type 
     self.params = { 
      'page': 0, 
      'sort': sort_type, 
      'role': role_type, 
      'job_type': job_type, 
      'title_type': title_type 
     } 

    def identity(self): 
     """gets actor's name and extracts its id from 
     imdb website.""" 
     response = rq.get(IMDB_JSON, params={'json': 1, 'nm': 'one', 
          'q': rq.compat.quote_plus(self.role_type)}) 
     movie_dicts = response.json() 
     return movie_dicts.get('name_popular', 'name_approx')[0]['id'] 

    def selector(self, expr): 
     """gets an expression and extracts all matched then 
     returns a generator of each matching value.""" 
     self.params['role'] = self.identity() 
     while True: 
      self.params['page'] += 1 
      response = rq.get(IMDB_HTML, params=self.params) 
      elements = lxml.html.fromstring(response.text).xpath(expr) 
      if not elements: 
       break 
      yield from (element.text for element in elements) 


class IMDBApplication(IMDBParser): 
    def __init__(self, role_type=None, sort_type='user_rating, desc', 
       job_type="actor", title_type="movie"): 
     IMDBParser.__init__(self) 
     self.job_type = job_type 
     self.sort_type = sort_type 
     self.title_type = title_type 
     self.role_type = role_type 

    def get_titles(self): 
     """passes the xpath expression to the function and gets 
     its return.""" 
     expr = "//*/div/div[2]/div[3]/div/div[2]/h3/a[1]" 
     return self.selector(expr) 

    def get_scores(self): 
     """passes the xpath expression to the function and gets 
     its return.""" 
     expr = "//*/div[2]/div[3]/div/div[2]/div/div[1]/strong" 
     return self.selector(expr) 

    def get_years(self): 
     """passes the xpath expression to the function and gets 
     its return.""" 
     expr = "//*/div/div[2]/div[3]/div/div[2]/h3/span[2]" 
     return self.selector(expr) 

if __name__ == "__main__": 
    ia1 = IMDBApplication("Daniel Craig") 
    print([i for i in ia1.get_titles()]) 
    print([i for i in ia1.get_scores()]) 
+1

Как именно это сломать? Пожалуйста, предоставьте более подробную информацию. – Necreaux

+0

@peterh - Обзор кода предназначен для рабочего кода, а не для отладки – rolfl

+0

@rolfl Я могу понять, почему. Благодаря! – peterh

ответ

1

Проблема заключается в том:

self.params['page'] += 1 

первый запрос, вы увеличиваете количество страниц до тех пор, пока вы не получите никаких результатов. Однако вы никогда не перезагружаете его. Если вы измените selector функцию:

def selector(self, expr): 
    """gets an expression and extracts all matched then 
    returns a generator of each matching value.""" 
    self.params['role'] = self.identity() 
    while True: 
     self.params['page'] += 1 
     response = rq.get(IMDB_HTML, params=self.params) 
     elements = lxml.html.fromstring(response.text).xpath(expr) 
     if not elements: 
      break 
     yield from (element.text for element in elements) 
    self.params['page'] = 0 

Он отлично работает, давая:

['Casino Royale', 'The Girl with the Dragon Tattoo', 'One Life', 'Skyfall', 'Road to Perdition', 'Munich', 'Elizabeth', 'Layer Cake', 'The Adventures of Tintin: The Secret of the Unicorn', 'Defiance', 'The Power of One', 'The Jacket', 'Infamous', 'Sorstalanság', 'The Mother', 'Flashbacks of a Fool', 'Renaissance', 'Ten Minutes Older: The Cello', 'Quantum of Solace', 'Some Voices', 'Love Is the Devil: Study for a Portrait of Francis Bacon', 'Hotel Splendide', 'Enduring Love', 'Sylvia', 'The Golden Compass', 'Cowboys & Aliens', 'The Trench', 'Dream House', 'The Invasion', 'Lara Croft: Tomb Raider', 'I Dreamed of Africa', 'Obsession', 'Love & Rage', 'Saint-Ex', "A Kid in King Arthur's Court", 'Spectre', 'The Girl Who Played with Fire', 'Bond 25', "The Girl Who Kicked the Hornets' Nest"] 
['8.0', '7.9', '7.9', '7.8', '7.7', '7.6', '7.5', '7.4', '7.4', '7.2', '7.2', '7.1', '7.1', '7.1', '6.9', '6.8', '6.8', '6.8', '6.7', '6.7', '6.6', '6.5', '6.4', '6.3', '6.1', '6.1', '6.1', '5.9', '5.9', '5.7', '5.5', '5.3', '5.3', '5.1', '4.7'] 

 Смежные вопросы

  • Нет связанных вопросов^_^