美文网首页
scrapy爬取豆瓣电影top250榜单(学习笔记)

scrapy爬取豆瓣电影top250榜单(学习笔记)

作者: 呆呆冬 | 来源:发表于2017-09-07 15:40 被阅读172次

    相关工具


    • Python 3.6.1
    • Scrapy 1.4.0
    • PyCharm (亲测VS Code无法运行、调试scrapy代码)

    创建一个scrapy项目


    在你的工作目录的文件夹下打开命令提示符窗口,输入:

    scrapy startproject demo

    如果出现下面的提示,则说明创建成功:

    image.png

    使用PyCharm打开这个scrapy项目,它的目录结构是这样的:

    image.png
    • scrapy.cfg ——主要包含的是项目的相关设置。
    • demo ——是用于编写爬虫的目录。
    • items.py ——定义我们所要爬取的信息的相关属性。
    • middlewares.py ——爬虫中间件,这里可以用过自定义相关的方法,用来处理爬虫的响应和请求。
    • pipelines.py ——当数据被爬虫爬取下来后,它会被发送到item pipelines中,每个item pipelines组件(有时称为“项目管道”)是一个实现简单方法的Python类。他们收到一个项目并对其执行操作,还决定该项目是否应该继续通过管道或被丢弃并且不再被处理。
    • settings.py ——项目的设置文件。

    编写代码


    在spiders文件夹下创建douban_spider.py文件:

    image.png

    这是一个空的.py文件,然后在这编写爬虫代码:

    # 爬虫类需要继承scrapy下的Spider类。
    import scrapy
    
    class douban_movie_spider(scrapy.Spider):
        # 项目的启动名
        name = "douban_movie"
        # 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
        headler = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
                          'Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
        }
        # 开始链接
        start_urls = [
            'https://movie.douban.com/top250'
        ]
        # start_requests方法为scrapy的方法,我们对它进行重写。
        def start_requests(self):
           # 将start_url中的链接通过for循环进行遍历。
           for url in self.start_urls:
                 # 通过yield发送Request请求。
                 # 这里的Reques注意是scrapy下的Request类。注意不要导错类了。
                 # 这里的有3个参数:
                 # 1、url为遍历后的链接
                 # 2、callback为发送完请求后通过什么方法进行处理,这里通过parse方法进行处理。
                 # 3、如果网站设置了防爬措施,需要加上headers伪装浏览器发送请求。
                
               yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)
    
        # 重写parse对start_request()请求到的数据进行处理
        def parse(self, response):
           pass
    

    页面分析


    chrome浏览器打开https://movie.douban.com/top250,点击f12开发者工具,使用选取工具选取整个电影的信息,可以发现,所有的信息都是放在单独的一个li标签中的,而且在li下还有一个class为item的div包裹着所有的信息:

    image.png

    parse方法


    def parse(self, response):
        # 这里使用scrapy的css选择器,既然数据在class为item的div下,那么把选取范围定位div.item
        for quote in response.css('div.item'):
            # 通过yield对网页数据进行循环抓取,我们要抓取的内容有3个,分别如下
            yield {
                "电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
                "评分":quote.css('div.info div.bd div.star span.rating_num::text').extract(),
                "引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
            }
    

    写完上面的代码,其实只是抓取一页的罢了,为了抓取完整的top250榜单,我们需要让爬虫跳转到下一页再进行循环抓取,因为每个页面的结构是一样的,所以不用担心会抓取不到。

    image.png
    next_url=response.css('div.paginator span.next a::attr(href)').extract()
    

    然后,需要对next_url进行判断是否存在,然后再次发送Request请求。这样爬虫就会在爬完一个页面后点击下一页再继续爬去,往复循环,直到爬取完毕。

    if next_url:
        next_url="https://movie.douban.com/top250"+next_url[0]
        print(next_url)
        yield scrapy.Request(next_url,headers=self.headler)
    

    那么到这里,代码就写完了。

    然后我们来运行一下这个爬虫,scrapy框架是通过命令来启动爬虫的,
    在项目根目录下打开命令提示符,输入:

    scrapy crawl douban_movie -o douban_movice.csv -t csv

    保存信息的最简单的方法是通过Feed exports,主要有四种:JSON,JSON lines,CSV,XML。
    为了方便直接查看内容,我们将结果用csv导出。
    -o 后面是导出文件名,-t 后面是导出类型。

    爬虫运行后,就会输出大量的日志信息和爬取的网页内容,且scrapy会把爬取到的结果保存到douban_movice.csv这个文件里:


    image.png image.png image.png

    但是,有个问题,如果爬虫报错了怎么办?

    因为是用命令启动的爬虫,所以爬虫的日志信息都是显示在cmd中的,这样日志信息阅读起来非常的不友好。且Scrapy默认是不能在IDE中调试的,我们可以在根目录中新建一个run.py文件,在里面写入以下内容:

    image.png
    from scrapy import cmdline
    
    name='douban_movie -o douban.csv -t csv'
    cmd = 'scrapy crawl {0}'.format(name)
    cmdline.execute(cmd.split())
    

    运行这个文件后,所有的日志信息日志信息就会输出在IDE(PyCharm)下了,便于调试:

    image.png

    在PyCharm中查看爬取结果:

    image.png

    完整代码


    # 爬虫类需要继承scrapy下的Spider类。
    import scrapy
    
    
    class douban_movie_spider(scrapy.Spider):
        # 项目的启动名
        name = "douban_movie"
    
        # 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
        headler = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
                          'Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
        }
        # 开始链接
        start_urls = ['https://movie.douban.com/top250']
    
        # start_requests方法为scrapy的方法,我们对它进行重写。
        def start_requests(self):
            # 将start_url中的链接通过for循环进行遍历。
            for url in self.start_urls:
    
                # 通过yield发送Request请求。
                # 这里的Reques注意是scrapy下的Request类。注意不到导错类了。
                # 这里的有3个参数:
                # 1、url为遍历后的链接
                # 2、callback为发送完请求后通过什么方法进行处理,这里通过parse方法进行处理。
                # 3、如果网站设置了防爬措施,需要加上headers伪装浏览器发送请求。
    
                yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)
    
        # 重写parse对start_request()请求到的数据进行处理
        def parse(self, response):
            # 这里使用scrapy的css选择器,既然数据在class为item的div下,那么把选取范围定位div.item
    
            for quote in response.css('div.item'):
                # 通过yield对网页数据进行循环抓取,我们要抓取的内容有3个,分别如下
    
                yield {
                    "电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
                    "评分": quote.css('div.info div.bd div.star span.rating_num::text').extract(),
                    "引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
                }
    
            next_url = response.css('div.paginator span.next a::attr(href)').extract()
            if next_url:
                next_url = "https://movie.douban.com/top250"+next_url[0]
                print(next_url)
                yield scrapy.Request(next_url, headers=self.headler)
    
            # 翻页
            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)
    

    参考文章:https://segmentfault.com/a/1190000009091789

    相关文章

      网友评论

          本文标题:scrapy爬取豆瓣电影top250榜单(学习笔记)

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