爬虫学习-scrapy爬取豆瓣电影top250

scrapy爬取豆瓣电影top250

学习一下爬虫,在网上看了几个教程,毕竟实践后理解才更深,遂自己跑一下。

工具和环境

  • scrapy 1.5.0
  • python 3.5
  • chrome

scrapy的简单认识

scrapy的数据流图

爬虫学习-scrapy爬取豆瓣电影top250_第1张图片

  • 引擎打开一个网站(open a domain),找到处理该网站的Spider并向该spider请求第一个要爬取的URL(s)。
  • 引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)以Request调度。
  • 引擎向调度器请求下一个要爬取的URL。
  • 调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件(请求(request)方向)转发给下载器(Downloader)。
  • 一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(返回(response)方向)发送给引擎。
  • 引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。
  • Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎。
  • 引擎将(Spider返回的)爬取到的Item给Item Pipeline,将(Spider返回的)Request给调度器。
  • (从第二步)重复直到调度器中没有更多地request,引擎关闭该网站。

创建项目

scrapy startproject moviespider

爬虫学习-scrapy爬取豆瓣电影top250_第2张图片

  • items.py 定义需要获取的内容字段
  • middlewares.py 爬虫中间件,这里可以用过自定义相关的方法,用来处理爬虫的响应和请求。
  • pipelines.py 用来对Spider爬取的数据进行处理
  • setting.py 项目设置文件
  • scrapy.cfg 项目配置文件

定义item(items.py)

Item 对象保存爬取的数据的容器,其提供了类似于词典(dictionary-like) 的API以及用于声明可用字段的简单语法。

这里在items.py定义爬取的内容,电影排名ranking,名称name和评分score。

import scrapy
class MoviespiderItem(scrapy.Item):
    # define the fields for your item here like:
    ranking = scrapy.Field()
    name = scrapy.Field()
    score = scrapy.Field()

编写爬虫(movie_spider.py)

Spider类中定义抓取对象(域名、URL)以及抓取的规则,创建自己的Spider,必须继承 scrapy.Spider 类, 且定义以下三个属性:

  • name: 用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
  • start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
  • parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。 该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。

在moviespider/spiders下创建douban_spider.py

import scrapy
from scrapy.spiders import Spider
from moviespider.items import MoviespiderItem


class MovieTop250Spider(Spider):
    name = 'movie_top250'
    # 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
    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',
    }
    start_urls = [
        'https://movie.douban.com/top250'
    ]

    # start_requests方法为scrapy的方法,对它进行重写。
    # 该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取的第一个Request。当spider启动爬取并且未制定URL时,该方法被调用。
    # 当指定了URL时,make_requests_from_url() 将被调用来创建Request对象。
    # 该方法仅仅会被Scrapy调用一次,因此您可以将其实现为生成器。
    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url=url, callback=self.parse, headers=self.headers)

    def parse(self, response):
        pass

提取页面信息

打开豆瓣电影top250页面https://movie.douban.com/top250,command+alt+i(windows下为f12)打开开发者工具,用抓取工具(在左上角)选择找到信息所在的标签。

可以找到这里的电影信息在一个叫class属性为grid_view的ol标签内的li标签内,在class=item的div下。

爬虫学习-scrapy爬取豆瓣电影top250_第3张图片

parse页面信息

从response里面解析或者说提取出要爬取的信息,可以实用XPath,CSS,beautifulsoup等,我都是第一次接触,都不太熟悉,看了XPath和CSS的提取方法后,个人感觉CSS的语法干净一点,就选择CSS了。beautifulsoup其实感觉也不错,会把html变为python的对象,转化成字典和数组,可能更好用,后面学习一下怎么用。一个讲beautifulsoup的博客链接

    def parse(self, response):
        item = MoviespiderItem()
        for quote in response.css('div.item'):
            item['name'] =  quote.css('div.info div.hd a span.title::text').extract_first()
            item['ranking'] = quote.css('div.pic em::text').extract()
            item['score'] = quote.css('div.info div.bd div.star span.rating_num::text').extract()
            yield item

        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.headers)

自动翻页

不能只让爬虫爬一页的信息,为了爬到完整的信息,需要让它自己翻页去下一页,实现自动翻页一般有两种方法:

  • 在页面中找到下一页的地址;
  • 自己根据URL的变化规律构造所有页面地址。

我们选择第二种,跟前面一样,在html中用css提取到next页的地址,然后继续发送request请求,这里的代码在上面的parse函数。

运行看结果

在命令行运行

scrapy crawl movie_top250 -o movie_list.csv

部分爬取结果

爬虫学习-scrapy爬取豆瓣电影top250_第4张图片

爬虫学习-scrapy爬取豆瓣电影top250_第5张图片

你可能感兴趣的:(Python,python,爬虫)