美文网首页
【scrapy】爬取豆瓣top250的电影信息

【scrapy】爬取豆瓣top250的电影信息

作者: Julianlee107 | 来源:发表于2017-08-08 23:22 被阅读0次

    前言

    利用scrapy爬取豆瓣上top250条电影信息其实挺容易的,主要是用来熟悉一下如何利用scrapy快速写一个爬虫。

    开始启动一个scrapy项目

    进入到想要创建scrapy项目的目录下

    scrapy startproject douban_top_250
    

    当我们想要写一个爬虫的时候后要知道我们想要从哪爬取,想要爬取什么,爬取下来的数据我们需要进行什么样的处理。

    设计需要爬取的item

    先打开豆瓣电影top250这个页面。


    可以看到这个页面展示了电影的名字、排名、导演、演员等信息。当我们点击每一个链接时还会有更多的信息:

    例如《肖申克的救赎》,这个详情页面展示了评分评论数还有用户给出的评论等信息。
    所以,我们可以爬取下这部电影的名称、导演、编剧、主演、类型、制片国家、语言、上映时间、片长、别名、排名、评分,评论人数等信息。

    import scrapy
    #items.py
    #这个文件
    class Douban_Top_250Item(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        chinese_name = scrapy.Field()
        english_name = scrapy.Field()
        director = scrapy.Field()
        screenwriter = scrapy.Field()
        main_actors = scrapy.Field()
        type = scrapy.Field()
        district = scrapy.Field()
        show_date = scrapy.Field()
        duration = scrapy.Field()
        other_name = scrapy.Field()
        score = scrapy.Field()
        rank = scrapy.Field()
        language = scrapy.Field()
        count_conmment = scrapy.Field()
    

    开始着手Spider

    from scrapy import Spider
    from scrapy.http import Request
    class crawlDoubanMovie(Spider):
        name = "douban_top_250"
        #因为豆瓣屏蔽了scrapy默认的header。
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36',
        }
        def start_requests(self):
            url = 'https://movie.douban.com/top250'
            yield Request(url, headers=self.headers)
        def parse(self,response):
             #后面单独来写。
            pass
          
        }
    

    这样实现了一个能访问豆瓣电影top250的超简单爬虫。
    parse函数是scrapy中用来对url进行处理的默认函数,也可以在Request中加入新的callback函数。

    #在crawlDoubanMovie前面有4个indent。暂时省略了
        def parse(self, response):
            #将每部电影的URL传入到一个专门的函数中进行数据提取,也可以直接在parse函数中进行处理
            post_urls = response.xpath('//ol[@class="grid_view"]/li//div[@class="hd"]/a/@href').extract()
            for post_url in post_urls:
                yield Request(url =parse.urljoin(response.url,post_url),callback=self.parse_detail,headers=self.headers)
          
    

    使用了XPath对节点进行了选择


    在对页面中每一个电影的链接进行请求后,这个页面的有用信息基本上就爬取完成,还剩下一个很重要的操作,就是对下一页的链接进行请求然后进行爬取。通过查看页面,发现可以对“后页”这个链接进行请求


    最后一页时后页无链接

    也可以对下面的“1,2,3,4....”链接进行获取,不过这样只能针对页数很少的网站。

    def parse(self,response):
         ...
        next_url = response.xpath('//*[@id="content"]/div/div[1]/div[2]/span[3]/a/@href').extract_first()
            yield Request(parse.urljoin(response.url,next_url),headers=self.headers)
    

    自定义一个parse_detail函数,对电影详情页面的数据进行处理。

    #我使用了ItemLoader,也可以不使用loader直接将值通过键值对的形式传给Item.py
    from scrapy.loader import ItemLoader
        def parse_detail(self,response):
            text_xpath="//*[@id='info']/text()"
            text = [element.strip() for element in response.xpath(text_xpath).extract()]
            while "" in text:
                text.remove("")
            while "/" in text:
                text.remove("/")
            print(text)
            movieItemLoader = ItemLoader(item=Douban_Top_250Item(),response=response)
            movieItemLoader.add_xpath("chinese_name","//*[@id='content']/h1/span[1]/text()")
            movieItemLoader.add_xpath("english_name","//h1/span[1]/text()")
            movieItemLoader.add_xpath("director","//*[@id='info']/span[1]/span[@class='attrs']/a/text()")
            movieItemLoader.add_xpath("screenwriter","//*[@id='info']/span[2]/span[@class='attrs']/a/text()")
            movieItemLoader.add_xpath("main_actors",'//*[@id="info"]/span[3]/span[@class="attrs"]/a/text()')
            movieItemLoader.add_xpath("type",'//*[@id="info"]/span[@property="v:genre"]/text()')
            movieItemLoader.add_value("district",text[0])
            movieItemLoader.add_value("language",text[1])
            movieItemLoader.add_value("other_name",text[2])
            movieItemLoader.add_xpath("show_date",'//*[@id="info"]/span[@property="v:initialReleaseDate"]/text()')
            movieItemLoader.add_xpath("duration",'*[@id="info"]/span[@property="v:runtime"]/text()')
            movieItemLoader.add_xpath("rank",'//*[@id="content"]/div[1]/span[1]/text()')
            movieItemLoader.add_xpath("count_comment","//span[@property=v:votes]/text()")
            movieItemLoader.add_xpath("score",'//span[@property="v:average"]/text()')
            movieItem = movieItemLoader.load_item()
            yield movieItem
    
    

    上面代码中的text是为了处理

    纯文本

    这样的纯文本,它存在于父节点的文本中,所以要进行处理才能提取到。(个人感觉是豆瓣很懒。。。写的很难看)

    关于ItemLoader

    ItemLoader中将所有爬取到的信息都设置为list,所以要设置好ItemLoader的output_processors。通过查看ItemLoader的源码


    可以看到,我们可以改变default_output_processor
    那么我们在item中进行写一个自己的ItemLoader

    #items.py
    from scrapy.loader.processors import TakeFirst
    class MovieItemLoader(ItemLoader):
        default_output_processor = TakeFirst
    

    这样就可以将返回的item中取出list中的第一个元素。可是有的数据本身就是一个list,我们可以通过一个方法,将默认的输出给覆盖掉。

    def return_value(value):
        return value
    

    value即是itemloader所传入的值
    既然要使用自己写的ItemLoader,就需要在spider中修改使用的默认ItemLoader

    from ..items import MovieItemLoader
        ...
         movieItemLoader = MovieItemLoader(item=Douban_Top_250Item(),response=response
        ...
    )
    

    剩下的即是在items中写一些方法将itemloader传入的value进行input_processor和output_processor的处理。使用的大概方法即是在scrapy.Filed()中添加方法,可以使用MapCompose将多个方法组合在
    一起。
    例如:

    screenwriter = scrapy.Field(
                    input_processor=方法,
                    output_processor=方法
    )
    

    最后

    最后肯定要将采集好的数据进行存储。可以使用两种方式:一种是使用scrapy自带的feed export,另一种是自己写pipeline将数据保存为自己想要的格式,例如存入到数据库,保存为CSV,保存为json等。
    以后接着写,to be continued

    最后的最后

    今天晚上九寨沟发生了7级地震,希望同胞安好

    相关文章

      网友评论

          本文标题:【scrapy】爬取豆瓣top250的电影信息

          本文链接:https://www.haomeiwen.com/subject/dryxrxtx.html