Làm thế nào để cạo trang web imdb?


10

Tôi đang cố gắng tự học quét web bằng Python như một phần của nỗ lực học phân tích dữ liệu. Tôi đang cố gắng cạo trang web imdb có url như sau: http://www.imdb.com/search/title?sort=num_votes,desc&start=1&title_type=feature&year=1950,2012

Tôi đang sử dụng mô-đun BeautifulSoup. Sau đây là mã tôi đang sử dụng:

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

Tôi nhận được kết quả đầu ra sau đây:

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

Sử dụng mã này, tôi có thể loại bỏ tiêu đề, thể loại, thời gian chạy và năm nhưng tôi không thể cạo id phim imdb, cũng như xếp hạng. Sau khi kiểm tra các yếu tố (trong trình duyệt chrome), tôi không thể tìm thấy một mẫu nào cho phép tôi sử dụng mã tương tự như trên.

Ai đó có thể giúp tôi viết đoạn mã sẽ cho phép tôi cạo id phim và xếp hạng không?


1
Tôi đã chỉnh sửa mã của bạn một chút nhưng không thành công vì ratingkhông được xác định. Nếu bạn sửa nó, bạn cũng có thể thêm from BeautifulSoup import BeautifulSoupimport requests. Và tại sao không thể hiện url="http://etc"để chúng ta không phải làm điều đó cho chính mình?
Spainedman

Câu trả lời:


12

Thay vì cạo, bạn có thể thử lấy dữ liệu trực tiếp tại đây: http://www.imdb.com/interfaces . Có vẻ như họ có sẵn dữ liệu qua ftp cho phim, diễn viên, v.v.


2
@Gred Thatcher, Cảm ơn đã liên kết. Dự án này là một phần của nỗ lực học tập về quét web và do đó tất cả những rắc rối này. - :)
user62198

8

Tôi đã có thể tìm ra một giải pháp. Tôi đã nghĩ đến việc đăng bài chỉ trong trường hợp nó có ích cho bất kỳ ai hoặc nếu ai đó muốn đề xuất một cái gì đó khác biệt.

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

Đầu ra trông như thế này:

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

2

Bạn có thể nhận mọi thứ từ div với class = "rating rating-list"

Tất cả những gì bạn cần làm là truy xuất lại thuộc tính id: [id = "tt1345836 | imdb | 8.5 | 8.5 | advsearch"] Khi bạn có nội dung này, bạn chia chuỗi này cho '|' và bạn nhận được: 1. tham số: id phim 3. tham số: điểm phim


Cảm ơn. @Matic DB ... tôi đã có thể lấy id ..Below là giải pháp của tôi
user62198

2

Là một chút thông tin phản hồi chung, tôi nghĩ bạn sẽ làm tốt để cải thiện định dạng đầu ra của mình. Vấn đề với định dạng như hiện tại là không có cách minh bạch để lấy dữ liệu theo chương trình. Hãy xem xét thay vì cố gắng:

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

Điều thú vị về một tệp được phân định bằng tab là nếu bạn kết thúc mở rộng, nó có thể dễ dàng được đọc thành một cái gì đó như impala (hoặc ở quy mô nhỏ hơn, các bảng mySql đơn giản). Ngoài ra, sau đó bạn có thể đọc chương trình trong dữ liệu bằng python bằng cách sử dụng:

 line.split("\t")

Lời khuyên thứ hai, là tôi sẽ đề nghị nhận được nhiều thông tin hơn bạn nghĩ bạn cần trên bản thảo ban đầu của mình. Dung lượng ổ đĩa rẻ hơn thời gian xử lý, do đó, việc chạy lại trình cào mỗi khi bạn mở rộng phân tích sẽ không thú vị.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.