Jak zeskrobać stronę IMDB?

10

Próbuję nauczyć się skrobania stron internetowych przy użyciu Pythona jako część wysiłku uczenia się analizy danych. Próbuję zeskrobać stronę internetową imdb, której adres URL jest następujący: http://www.imdb.com/search/title?sort=num_votes,desc&start=1&title_type=feature&year=19502012

Korzystam z modułu BeautifulSoup. Oto kod, którego używam:

r = requests.get(url) # where url is the above url    
bs = BeautifulSoup(r.text)
for movie in bs.findAll('td','title'):
    title = movie.find('a').contents[0]
    genres = movie.find('span','genre').findAll('a')
    genres = [g.contents[0] for g in genres]
    runtime = movie.find('span','runtime').contents[0]
    year = movie.find('span','year_type').contents[0]
    print title, genres,runtime, rating, year

Otrzymuję następujące wyniki:

The Shawshank Redemption [u'Crime', u'Drama'] 142 mins. (1994)

Za pomocą tego kodu mogłem zeskrobać tytuł, gatunek, środowisko uruchomieniowe i rok, ale nie mogłem zeskrobać identyfikatora filmu imdb ani oceny. Po sprawdzeniu elementów (w przeglądarce Chrome) nie jestem w stanie znaleźć wzoru, który pozwoli mi użyć podobnego kodu jak powyżej.

Czy ktoś może mi pomóc napisać fragment kodu, który pozwoli mi zeskrobać identyfikator filmu i oceny?

użytkownik62198
źródło
1
Zmodyfikowałem trochę twój kod, ale nie działa, ponieważ ratingnie został zdefiniowany. Jeśli to naprawisz, możesz również dodać from BeautifulSoup import BeautifulSoupi import requests. A dlaczego nie pokazać url="http://etc", żebyśmy nie musieli tego robić dla siebie?
Spacedman
1
Na wszelki wypadek: opendata.stackexchange.com/questions/1073/...
Anton Tarasenko

Odpowiedzi:

12

Zamiast skrobania możesz spróbować uzyskać dane bezpośrednio tutaj: http://www.imdb.com/interfaces . Wygląda na to, że mają dane dostępne przez ftp do filmów, aktorów itp.

Greg Thatcher
źródło
2
@Gred Thatcher, dzięki za link. Ten projekt jest częścią procesu uczenia się dotyczącego zgarniania stron internetowych, a tym samym wszystkich tych problemów. - :)
user62198
8

Udało mi się znaleźć rozwiązanie. Pomyślałem o zamieszczeniu postu na wypadek, gdyby był komuś pomocny lub ktoś chciałby zasugerować coś innego.

bs = BeautifulSoup(r.text)
for movie in bs.findAll('td','title'):
    title = movie.find('a').contents[0]
    genres = movie.find('span','genre').findAll('a')
    genres = [g.contents[0] for g in genres]
    runtime = movie.find('span','runtime').contents[0]
    rating = movie.find('span','value').contents[0]
    year = movie.find('span','year_type').contents[0]
    imdbID = movie.find('span','rating-cancel').a['href'].split('/')[2]
    print title, genres,runtime, rating, year, imdbID

Dane wyjściowe wyglądają następująco:

The Shawshank Redemption [u'Crime', u'Drama'] 142 mins. 9.3 (1994) tt0111161
użytkownik62198
źródło
2

Możesz uzyskać wszystko od div z class = "rating rating-list"

Wszystko, co musisz zrobić, to pobrać identyfikator atrybutu: [id = "tt1345836 | imdb | 8.5 | 8.5 | advsearch"] Gdy masz tę zawartość, dzielisz ten ciąg na „|” i otrzymujesz: 1. parametr: identyfikator filmu 3. parametr: wynik filmu

MaticDiba
źródło
Dzięki. @Matic DB ... udało mi się uzyskać identyfikator .. Poniżej znajduje się moje rozwiązanie
user62198 16.0415
2

Jako ogólną informację zwrotną uważam, że dobrze by było, gdybyś poprawił swój format wyjściowy. Problem z obecnym formatem polega na tym, że nie ma przejrzystego sposobu na programowe uzyskanie danych. Zamiast tego rozważ:

print "\t".join([title, genres,runtime, rating, year])

Zaletą pliku rozdzielanego tabulatorami jest to, że jeśli skalujesz w górę, możesz go łatwo odczytać w coś takiego jak impala (lub w mniejszych skalach, proste tabele mySql). Dodatkowo możesz programowo odczytać dane w pythonie, używając:

 line.split("\t")

Druga rada: sugeruję, aby uzyskać więcej informacji, niż myślisz, że potrzebujesz na początkowym zadrapaniu. Miejsce na dysku jest tańsze niż czas przetwarzania, więc ponowne uruchamianie skrobaka za każdym razem, gdy rozszerzysz swoją analizę, nie będzie zabawne.

jagartner
źródło