博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
scrapy入门教程——爬取豆瓣电影Top250!
阅读量:6264 次
发布时间:2019-06-22

本文共 9463 字,大约阅读时间需要 31 分钟。

本课只针对python3环境下的Scrapy版本(即scrapy1.3+)

选取什么网站来爬取呢?

对于歪果人,上手练scrapy爬虫的网站一般是官方练手网站

我们中国人,当然是用豆瓣Top250啦!

clipboard.png

第一步,搭建准备

  1. 为了创造一个足够干净的环境来运行scrapy,使用virtualenv是不错的选择。
>>> mkdir douban250 && cd douban250>>> virtualenv -p python3.5 doubanenv

首先要保证已经安装有virtualenv和python3.x版本,上面命令为创建python3.5环境的virtualenv

virtualenv教程:

  1. 开启virtualenv,并安装scrapy
>>> source doubanenv/bin/activate>>> pip install scrapy
  1. 使用scrapy初始化项目一个项目,比如我们命名为douban_crawler
>>> scrapy startproject douban_crawler

这时生成了一个目录结构

douban_crawler/    douban.cfg    douban_crawler/        __init__.py        items.py        middlewares.py        piplines.py        setting.py

并且命令行会给你一个提示:

You can start your first spider with:    cd douban_crawler    scrapy genspider example example.com
  1. 按提示执行这两步吧!
>>> cd douban_crawler>>> scrapy genspider douban movie.douban.com/top250

genspider后目录结构中增加了spider目录

douban_crawler/    douban.cfg    douban_crawler/        spiders/            __init__.py            douban.py        __init__.py        items.py        middlewares.py        piplines.py        setting.py

在pycharm中设置好项目

  1. 首先,在pycharm中打开douban_crawler/
  2. 然后设置pycharm的虚拟环境:

Perference > Project:douban_crawler > Project Interpreter

点击设置图标> Add Local > existing environment;把预置的python解析器,切换到刚刚创立的virtualenv下的doubanenv > bin > python3.5

开始爬取

准备工作完成,可以开始爬取了!

打开spiders/目录下的douban.py文件

# douban_crawler/ > spiders/ > douban.pyimport scrapyclass DoubanSpider(scrapy.Spider):    name = 'douban'    allowed_domains = ['movie.douban.com/top250']    start_urls = ['http://movie.douban.com/top250/']    def parse(self, response):        pass

start_urls就是我们需要爬取的网址啦!

把start_urls中的

改成

接下来我们将改写parse()函数,进行解析。

解析豆瓣250条目

使用chrome或firefox浏览器打开

使用右键菜单中的检查(inspect)分析元素,可以看出:

'.item'包裹了一个个词条

每一个词条下面

'.pic a img'的src属性包含了封面图片地址

'.info .hd a'的src属性包含了豆瓣链接
'.info .hd a .title'中的文字包含了标题,因为每个电影会有多个别名,我们只用取第一个标题就行了。
'.info .bd .star .rating_num'包含了分数
'.info .bd .quote span.inq'包含了短评

另外导演、年代、主演、简介等信息需要点击进入条目的才能爬取,我们先爬取以上五条信息吧!

按照刚刚的解析,填写parse()函数

# douban_crawler/ > spiders/ > douban.py# -*- coding: utf-8 -*-import scrapyclass DoubanSpider(scrapy.Spider):    name = 'douban'    allowed_domains = ['movie.douban.com/top250']    start_urls = ['https://movie.douban.com/top250/']    def parse(self, response):        items = response.css('.item')        for item in items:            yield {                'cover_pic': item.css('.pic a img::attr(src)').extract_first(),                'link': item.css('.info .hd a::attr(href)').extract_first(),                'title': item.css('.info .hd a .title::text').extract_first(),                'rating': item.css('.info .bd .star .rating_num::text').extract_first(),                'quote': item.css('.info .bd .quote span.inq::text').extract_first()            }

.css()运行类似于jquery或pyquery的解析器,但它可以用::text或::attr(href)来直接获取属性或文字,应当说比jquery解析器还要更方便。

当然,.css只能返回一个对象,而需要具体的文字或属性,则需要.extract()或.extract_first()

其中.extract()返回所有符合条件的文字或属性数组,而.extract_first()只返回查询到的第一条文字或属性。

在shell里验证解析语句是否正确

这里我们需要给大家一个窍门,就是先用shell验证刚刚写的css对不对

在pycharm窗口左下方打开terminal

命令行输入:

>>> scrapy shell https://movie.douban.com/top250

会出来一堆的返回信息,最后会出来一堆提示

[s] Available Scrapy objects:[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)[s]   crawler    
[s] item {}[s] request
[s] response <403 https://movie.douban.com/top250>[s] settings
[s] spider
[s] Useful shortcuts:[s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)[s] fetch(req) Fetch a scrapy.Request and update local objects [s] shelp() Shell help (print this help)[s] view(response) View response in a browser

我们看到response一项

——什么?返回的403错误?

原来我们爬取豆瓣没有设置User-Agent请求头,而豆瓣不接受无请求头的Get请求,最终返回了403错误。

这时赶紧在settings.py里面加入一行

#  spider_crawler/ > settings.pyUSER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'

保存文件后,重新运行

>>> scrapy shell https://movie.douban.com/top250

提示:

[s]   response   <200 https://movie.douban.com/top250>

这时就可以开始检验刚刚的解析语句能不能获得想要的结果了:

response.css('.item')

返回了一个<Selector>对象数组,我们取其中的第一个selector

>>> items = response.css('.item')>>> item = item[0]#把cover_pic对应的解析语句拷贝过来>>> item.css('.pic a img::attr(src)').extract_first()

返回

'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg'

即证明解析语句正确,其它的四项可以一一验证

>>> item.css('.pic a img::attr(src)').extract_first()'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg'>>> item.css('.info .hd a::attr(href)').extract_first()'https://movie.douban.com/subject/1292052/'>>> item.css('.info .hd a .title::text').extract_first()'肖申克的救赎'>>> item.css('.info .bd .star .rating_num::text').extract_first()'9.6'>>> item.css('.info .bd .quote span.inq::text').extract_first()'希望让人自由。'

这时候用exit()退出shell

再运行爬虫

>>> scrapy crawl douban

就可以看到解析后的数据输出了!

翻页爬取全部250条数据

刚刚我们初步爬取了一下,但这一页只显示25条,如何通过翻页爬到全部250条呢?

通过chrome浏览器的“检查”功能,我们找到豆瓣页面上的“下页”所对应的链接:

response.css('.paginator .next a::attr(href)')

现在我们改写一个douban.py

# douban_crawler/ > spiders/ > douban.pyclass DoubanSpider(scrapy.Spider):    name = 'douban'    allowed_domains = ['movie.douban.com/top250']    start_urls = ['https://movie.douban.com/top250']    def parse(self, response):        items = response.css('.item')        for item in items:            yield {                'cover_pic': item.css('.pic a img::attr(src)').extract_first(),                'link': item.css('.info .hd a::attr(href)').extract_first(),                'title': item.css('.info .hd a .title::text').extract_first(),                'rating': item.css('.info .bd .star .rating_num::text').extract_first(),                'quote': item.css('.info .bd .quote span.inq::text').extract_first()            }        next_page = response.css('.paginator .next a::attr(href)').extract_first()        if next_page:            next_page_real = response.urljoin(next_page)            yield scrapy.Request(next_page_real, callback=self.parse,dont_filter=True)

以上通过response.urljoin()返回了拼接后的真实url

然后通过一个递归返回Request对象,遍历了所有的页面。

注意!爬豆爬一定要加入dont_filter=True选项,因为scrapy只要解析到网站的Url有'filter=',就会自动进行过滤处理,把处理结果分配到相应的类别,但偏偏豆瓣url里面的filter为空不需要分配,所以一定要关掉这个选项。

这时再运行一次爬虫

>>> scrapy crawl douban

250条数据已经爬取出来啦!

存储数据到文件

很简单,运行爬虫时加个-o就输出啦!

>>> scrapy crawl douban -o douban.csv

于是你看到当前目录下多了一个.csv文件,存储的正是我们想要的结果!

你也可以用 .json .xml .pickle .jl 等数据类型存储,scrapy也是支持的!

利用Items把爬到的数据结构化

Scrapy的Item功能很类似于Django或其它mvc框架中的model作用,即把数据转化成固定结构,这样才能便出保存和展示。

我们打开 items.py文件,如下定义一个名为DoubanItem的数据类型。

# douban_clawler > items.pyimport scrapyclass DoubanItem(scrapy.Item):    title = scrapy.Field()    link = scrapy.Field()    rating = scrapy.Field()    cover_pic = scrapy.Field()    quote = scrapy.Field()

有了DoubanItem后,就可以改造douban.py里面的parse函数,使爬取的信息全部转化为Item形式啦

# -*- coding: utf-8 -*-import scrapyfrom douban_crawler.items import DoubanItemclass DoubanSpider(scrapy.Spider):    name = 'douban'    allowed_domains = ['movie.douban.com/top250']    start_urls = ['https://movie.douban.com/top250']    def parse(self, response):        items = response.css('.item')        for item in items:            yield DoubanItem({                'cover_pic': item.css('.pic a img::attr(src)').extract_first(),                'link': item.css('.info .hd a::attr(href)').extract_first(),                'title': item.css('.info .hd a .title::text').extract_first(),                'rating': item.css('.info .bd .star .rating_num::text').extract_first(),                'quote': item.css('.info .bd .quote span.inq::text').extract_first()            })        next_page = response.css('.paginator .next a::attr(href)').extract_first()        if next_page:            next_page_real = response.urljoin(next_page)            yield scrapy.Request(next_page_real, callback=self.parse,dont_filter=True)

非常简单,只修改了两行:

  1. 引入DoubanItem
  2. 原来yield的一个dict格式,现在直接在DoubanItem中传入dict就可以把dict转化成DoubanItem对象了!

现在你可以scrapy crawl douban再试一次爬取,看是不是已经转换成了DoubanItem形式了?

存储数据到MongoDB

有了DoubanItem数据结构,我们就可以保存进MongoDB啦!

保存到MongoDB,我们需要用到pipline组件,没错,就是上面那一堆文件中的piplines.py

之前我们确保两件事:

  1. mongodb服务已经开启。如果没有开启请sudo mongod开启本地。
  2. pymongo包已安装。如果没有安装请pip install pymongo

使用pipline,请记住四个字!

启!

(开启爬虫)对应于open_spider,在spider开启时调用

在这里面启动mongodb

承!

(承接爬取任务)对应于from_clawler,它有几个特点:

  1. 它是类对象,所以必须加上@classmethod。
  2. 只要有这个函数,它就一定会被调用。
  3. 它必须返回我们Pipline本身对象的实例。
  4. 它有进入Scrapy所有核心组件的能力,也就是说可以通过它访问到settings对象。

转!

(转换对象)对应于process_item,它有几个特点:

  1. 必须返回Item对象或raise DropItem()错误
  2. 在这个函数内将传入爬取到的item并进行其它操作。

合!

(闭合爬虫)于应于close_spider,在spider关闭是调用

我们可以在这个函数内关闭MongoDB

有了以上知道,我们上代码!

# douban_crawler > piplines.pyimport pymongoclass DoubanCrawlerPipeline(object):    def __init__(self, mongo_uri, mongo_db):        self.mongo_uri = mongo_uri        self.mongo_db = mongo_db    def open_spider(self, spider):        self.client = pymongo.MongoClient(self.mongo_uri)        self.db = self.client[self.mongo_db]    @classmethod    def from_crawler(cls, crawler):        return cls(            mongo_uri = crawler.settings.get('MONGO_URI'),            mongo_db = crawler.settings.get('MONGO_DB')        )    def process_item(self, item, spider):        self.db['douban250'].insert_one(dict(item))        return item    def close_spider(self, spider):        self.client.close()

同时在setting中添加MONGODB的配置

MONGO_URI = "localhost"MONGO_DB = "douban"

还有非常重要的一步!

在setting中打开pipline的注释!!

ITEM_PIPELINES = {   'douban_crawler.pipelines.DoubanCrawlerPipeline': 300,}

现在打开crawler

scrapy crawl douban

爬到的信息已经保存到数据库了!

clipboard.png

转载地址:http://aucpa.baihongyu.com/

你可能感兴趣的文章
Python比总统更受关注:关于Python的五个事实
查看>>
第二代NumPy?阿里开源超大规模矩阵计算框架Mars
查看>>
几小时的事儿,苹果刚发布iOS 11.2.1又被阿里安全工程师完美越狱
查看>>
react配置eslint
查看>>
Web 安全漏洞之 OS 命令注入
查看>>
大数据平台架构技术选型与场景运用
查看>>
每天一个设计模式之享元模式
查看>>
微服务调用链追踪中心搭建
查看>>
一个强大的图片压缩算法—近微信压缩机制的Luban
查看>>
『React Navigation 3x系列教程』createMaterialTopTabNavigator开发指南
查看>>
java基础(十一) 枚举类型
查看>>
Dependency Injection-依赖注入详解
查看>>
设计师图解TCP连接过程
查看>>
这其实是一个求助的文章
查看>>
你必须掌握的 RESTful 后端接口设计参考书
查看>>
翻译 | 摆脱浏览器限制的JavaScript
查看>>
兼容iOS 10:配置获取隐私数据权限声明
查看>>
Docker 使用笔记
查看>>
jest && vue
查看>>
前端每周清单第 36 期:深入 Vue 2.5 类型增强、Puppeteer 端到端测试、PayPal 跨域套装...
查看>>