Como raspar página imdb?

10

Estou tentando aprender a raspagem da Web usando Python sozinho como parte de um esforço para aprender a análise de dados. Estou tentando raspar a página da Web do imdb cujo URL é o seguinte: http://www.imdb.com/search/title?sort=num_votes,desc&start=1&title_type=feature&year=1950,2012

Estou usando o módulo BeautifulSoup. A seguir está o código que estou usando:

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

Estou recebendo as seguintes saídas:

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

Usando esse código, pude raspar o título, o gênero, o tempo de execução e o ano, mas não pude raspar o ID do filme imdb nem a classificação. Depois de inspecionar os elementos (no navegador chrome), não consigo encontrar um padrão que permita usar código semelhante ao descrito acima.

Alguém pode me ajudar a escrever o código que me permitirá raspar a identificação e as classificações do filme?

user62198
fonte
11
Editei um pouco o seu código, mas ele falha porque ratingnão está definido. Se você corrigir isso, também poderá adicionar from BeautifulSoup import BeautifulSoup, e import requests. E por que não mostrar também url="http://etc"para não precisarmos fazer isso por nós mesmos?
Spacedman
11
Apenas no caso: opendata.stackexchange.com/questions/1073/…
Anton Tarasenko 5/05

Respostas:

12

Em vez de raspar, você pode tentar obter os dados diretamente aqui: http://www.imdb.com/interfaces . Parece que eles têm dados disponíveis via ftp para filmes, atores etc.

Greg Thatcher
fonte
2
@ Thatcher Gred, Obrigado pelo link. Este projeto é parte de um esforço de aprendizado sobre raspagem da Web e, portanto, todos esses problemas. - :)
user62198
8

Consegui descobrir uma solução. Pensei em postar apenas para o caso de ajudar alguém ou se alguém quiser sugerir algo diferente.

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

A saída é assim:

The Shawshank Redemption [u'Crime', u'Drama'] 142 mins. 9.3 (1994) tt0111161
user62198
fonte
2

Você pode obter tudo, desde div com class = "rating rating-list"

Tudo o que você precisa fazer é recuperar o ID do atributo: [id = "tt1345836 | imdb | 8.5 | 8.5 | advsearch"] Quando você tem esse conteúdo, divide essa sequência por '|' e obtém: 1. parâmetro: id do filme 3. parâmetro: pontuação do filme

MaticDiba
fonte
Obrigado. @Matic DB ... Eu era capaz de obter o ID de ..Below é a minha solução
user62198
2

Como um feedback geral, acho que você faria bem em melhorar seu formato de saída. O problema com o formato atual é que não há uma maneira transparente de obter os dados de forma programática. Considere tentar:

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

O bom de um arquivo delimitado por tabulação é que, se você acabar aumentando, ele pode ser facilmente lido em algo como impala (ou em escalas menores, tabelas mySql simples). Além disso, você pode ler programaticamente os dados em python usando:

 line.split("\t")

O segundo conselho é que sugiro obter mais informações do que você pensa que precisa no seu raspar inicial. O espaço em disco é mais barato que o tempo de processamento, portanto, executar o raspador toda vez que você expandir sua análise não será divertido.

jagartner
fonte