Python三种方法抓取豆瓣电影 top 250

更新:因豆瓣版本更新,正文内代码已失效,修复后的代码放到了Github,主要变化:

  • 退2保平安,改用Python 3(free style)
  • 加入了随机生成User Agent(Scrapy的user agent明明白白表示自己是个机器人…这是旧代码抓不到任何数据的原因)
  • 更新了rate的xpath
  • 现在github repo里共有三个玩具爬虫,分别使用beautifulsoup、scrapy、selenium

下面是本文初始版,详述Python 2下的Scrapy方法:

第一次接触scrapy,想找个简单的页面尝试下,于是就抓了豆瓣电影TOP250。没什么技术含量,主要收获是了解了scrapy的基本功能、xpath以及python中Unicode的编码问题。

只想看结果的话请往后翻。

实现

items.py (scrapy)

import scrapy

class Movie250Item(scrapy.Item):
    rank = scrapy.Field()
    title = scrapy.Field()
    link = scrapy.Field()
    star = scrapy.Field()
    rate = scrapy.Field()
    quote = scrapy.Field()

spider_movie250.py (scrapy)

import scrapy
from movie250.items import Movie250Item

class Movie250Spider(scrapy.Spider):
  """docstring for Movie250Spider"""
  name = 'movie250'
  allowed_domains = ["douban.com"]
  start_urls = [
    "http://movie.douban.com/top250/"
  ]

  def parse(self, response):
    for info in response.xpath('//div[@class="item"]'):
      item = Movie250Item()
      item['rank'] = info.xpath('div[@class="pic"]/em/text()').extract()
      item['title'] = info.xpath('div[@class="pic"]/a/img/@alt').extract()
      item['link'] = info.xpath('div[@class="pic"]/a/@href').extract()
      item['star'] = info.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/em/text()').extract()
      item['rate'] = info.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span/text()').extract()
      item['quote'] = info.xpath('div[@class="info"]/div[@class="bd"]/p[@class="quote"]/span/text()').extract()
      yield item

    # 翻页
    next_page = response.xpath('//span[@class="next"]/a/@href')
    if next_page:
      url = response.urljoin(next_page[0].extract())
      yield scrapy.Request(url, self.parse)

以上代码写好后进入在Console里输入以下命令,以爬取数据并存入json文件中:

scrapy crawl movie250 -o items.json

得到的json文件采样:

[{"star": ["9.6"], "title": ["\u8096\u7533\u514b\u7684\u6551\u8d4e"], "quote": ["\u5e0c\u671b\u8ba9\u4eba\u81ea\u7531\u3002"], "rank": ["1"], "rate": ["628644\u4eba\u8bc4\u4ef7"], "link": ["http://movie.douban.com/subject/1292052/"]},
{"star": ["9.4"], "title": ["\u8fd9\u4e2a\u6740\u624b\u4e0d\u592a\u51b7"], "quote": ["\u602a\u8700\u9ecd\u548c\u5c0f\u841d\u8389\u4e0d\u5f97\u4e0d\u8bf4\u7684\u6545\u4e8b\u3002"], "rank": ["2"], "rate": ["598654\u4eba\u8bc4\u4ef7"], "link": ["http://movie.douban.com/subject/1295644/"]}]

最后自己再写一个output得到结果(主要注意编码问题,注释里已进行解释,print语句有点长Orz):

output.py

import json

def readMovieJson():
    inFile = open("D:\Users\Simon\movie250\items.json",'r',0)
    text = inFile.read() # text是str
    movie_dict = json.loads(text) # movie_dict是list
    for movie in movie_dict: # movie是dict
        rank = movie["rank"][0] # rank等都是Unicode
        title = movie["title"][0]
        link = movie["link"][0]
        star = movie["star"][0]
        rate = movie["rate"][0]
        if movie["quote"]:
            quote = movie["quote"][0]
        else: quote = "暂无".decode("utf-8")
        
        # str和Unicode不能混用,要么将Unicode类型encode为其他编码,
          要么将str类型decode为其他编码
        # python的内部使用Unicode,str如“电影: ”是字节串,由Unicode
          经过编码(encode)后的字节组成的
        # 与下句不同的另一种组合字符串方式:print "电影: " + title.encode("utf-8")
        print "top".decode("utf-8") + rank + ".".decode("utf-8") + \
              title + " 评分".dec1ode("utf-8") + star + \
              '('.decode("utf-8") + rate + ')'.decode("utf-8") + \
              "\n链接:".decode("utf-8") + link + \
              "\n豆瓣评论:".decode("utf-8") + quote + "\n"

结果

top1.肖申克的救赎 评分9.6(628644人评价)
链接:http://movie.douban.com/subject/1292052/
豆瓣评论:希望让人自由。

top2.这个杀手不太冷 评分9.4(598654人评价)
链接:http://movie.douban.com/subject/1295644/
豆瓣评论:怪蜀黍和小萝莉不得不说的故事。

top3.阿甘正传 评分9.4(528435人评价)
链接:http://movie.douban.com/subject/1292720/
豆瓣评论:一部美国近现代史。

top4.霸王别姬 评分9.4(430468人评价)
链接:http://movie.douban.com/subject/1291546/
豆瓣评论:风华绝代。

top5.美丽人生 评分9.4(291120人评价)
链接:http://movie.douban.com/subject/1292063/
豆瓣评论:最美的谎言。

(下略)

    原文作者:simoncos
    原文地址: https://www.jianshu.com/p/62e0a588ee0d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞