[可视化抓取]portia2.0尝鲜体验以及自动化畅想-数据存储入mongodb

总览

  • 环境
  • 分析
  • 猜想
  • 实施
  • 总结

环境

  • mac or ubuntu 16.04
  • docker

分析

上一章节,==> [可视化抓取]portia2.0尝鲜体验以及自动化畅想-数据输出以及原理分析 <== 我们已经分析了portia 数据 输出的方式,以及从代码的层面来分析它实际的运作原理,群里有小伙伴以及微信私信问我:大鱼,这个怎么和我们的数据库正常的结合呢?一般我们遇到问题,先对比之前的处理经验

回顾

我们在以前正常的scrapy数据入库,都是写好一个pipeline ,然后写好我们的业务代码,加载pipeline就可以写入到数据库里面了,OK,那大方向确定了,我们就正常的从这个方面着手。

准备

还是拿我们上次教程的cnblogs 里面的代码来做例子,目前,我们本地的portia docker 已经起来了,我们看一下状态,使用命令docker ps -a

当前将宿主机的9001 和docker 内部的 9001 绑定,暴露出http服务,我们在打开浏览器http://127.0.0.1:9001/ 是可以看到我们熟悉的服务界面了,这里就不详细的介绍了,关于使用和环境的搭建以及项目的生成,我们可以好好的参考我前面的两篇文章。

探究

我们首先进入docker 内部 ,使用命令

进入目录/app/data/projects 找到我们熟悉cnblogs项目,我们首先看一下整体的目录结构

对比一下我们之前的scrapy项目,我们只要写好pipeline ,在settings.py 里面加载好就ok了

settings.py的同级目录下,建立pipelines.py文件,我们这次先正常的输出内容就好,暂时不存入到任何的数据库

Ok ,我们添加到settings.py 里面添加我们的写好的pipeline

这样,我们就把cnblogs项目里面的pipelines.py 正常的加入到了我们的配置选项里面了,接下来我们来在里面运行我们的项目,切换到/app/data/projects 目录 ,使用命令:

文档所在:http://portia.readthedocs.io/en/latest/spiders.html#running-a-spider

结果输出

结果显示,这个文件压根就没有加载进去 ,下面就是本次章节的精彩猜想以及如何去分析一个项目了

猜想

命令

我们来仔细研究一下 portiacrawl 到底是一个怎么样的过程,既然有这个命令,我们直接拿到portia 的官方git里面搜一下 https://github.com/scrapinghub/portia/search?utf8=%E2%9C%93&q=portiacrawl&type=,通过筛查,发现是如下的文件使用

我们进一步查找bin/portiacrawl 这个脚本 https://github.com/scrapinghub/portia/blob/master/slybot/bin/portiacrawl,代码层里面 如下的代码值得查看

我们通过代码查看,基本所谓的portiacrawl 其实就是就是套了一层scrapy crawl 的命令 ,那这样,我们之前scrapy crawl spider_name -o result.json -t json 命令是不是也可以正常使用呢?直接将结果输出呢?

实践

还是一样,使用命令

奇迹出现了!我们看看本地文件夹 ,出现了test.json 结果就是我们所爬取的内容,这个时候,我们可以直接将test.json 导入到mongodb,其实也可以算是一种数据库输入的方法了,当然,我们要进一步的去研究pipelines.py的使用

深入

我们注意到 我们每次使用 portiacrawl 这个命令的时候,都会根据当前的 文件类似(是否为zip文件) 来加入一个这个命令

我们进一步去查看scrapy里面的command 关于-s 的用法是什么意思 ,参考文件 https://github.com/scrapy/scrapy/blob/master/scrapy/commands/__init__.py

参考里面的-s ,简单来看就是替换默认的原来settings.py 里面的配置选项为我们自己的值,OK,我们重新回到docker 内部,我们来找找这个SPIDER_MANAGER_CLASS 到底啥时候用到,因为portia docker内部的 scrapy版本和线上的是不一样的,所以我们直接来看docker 内部的scrapy ,路径如下

我们来找找这个SPIDER_MANAGER_CLASS 使用命令

我们得知是在 crawler.py 中使用的,进一步去查找相关的代码,得到

原来本质上就是使用了 SPIDER_LOADER_CLASS,关于这个键是如何使用的,我们可以反查scrapy的官方github分析https://github.com/scrapy/scrapy/search?utf8=%E2%9C%93&q=SPIDER_LOADER_CLASS&type=
简单来说,当我们每次使用命令的时候,加载配置的动作都有一个预加载的过程,这个加载的过程将我们用户自己写好的方法,逻辑,配置加载到写好的模版里面,这样就可以通过命令来执行我们的爬虫了。

结果

既然已经分析到这一步了,我们直接来看看今天的主角slybot.spidermanager.SlybotSpiderManager => https://github.com/scrapinghub/portia/blob/master/slybot/slybot/spidermanager.py

核心代码

在这里,我们看spider_cls ,这里我们直接加载了写好的IblSpider , IblSpider 是直接加载我们的json规则(上篇文章已经分析了相关的规则),然后直接执行,走到这里,我们终于明白原先在项目文件夹下写pipelines.py为什么没有毛用了,原来本质上还是跑的这个/app/slybot/slybot/spider.py 的IblSpider,所以如果要加载我们自己写好的pipeline 呢,直接在这个项目slybot里面加入我们的pipeline ,修改settings.py 就可以了。

实施

修改pipelines

首先,我们将写好的pipelines.py 放在/app/slybot/slybot/ 目录下,然后修改同目录下的settings.py文件

在ITEM_PIPELINES 节点,加入我们的slybot.pipelines.MongoPipeline

OK ,这一切做好,切回到/app/data/projects 目录,使用命令portiacrawl cnblogs www.cnblogs.com ,我们来看看效果:

i got the spider from the spider 已经正常的打印出来了

安装pymongo

我们在portia docker 里面使用pip 安装pymongo

修改pipelines.py文件内容为

注意:我这里使用的地址是192.168.1.52,因为我局域网内的机器(192.168.1.52)已经起了mongo 这样一个实例,所以可以直接从docker 里面直接访问,如果你要绑定在另外一个docker 数据 库,请参考docker link的相关语法以及怎么把容器的网络连接在一起

运行

跳转到 /app/data/projects 使用命令

运行结束,用mongo链接 192.168.1.52的mongo实例,查看内容

OK ,数据已经存入到里面了

总结

本次主要从

  • 分析问题
  • 猜想问题
  • 原理分析
  • 大胆实践

这几个步骤着手,拿到一个框架不要慌,源代码都摆在那里了,你还怕啃不下来,多分析,多动手,问题都会解决的,OK

点赞
  • Rick

    很有启发,谢谢!

    • bruce

      感谢 :razz:

  • Lam

    哈哈 受益匪浅
    因为portia生成的scrapy爬虫可以用命令行启动
    用scrapyd部署之后
    由于scrapy的设置支持在命令行传参(优先级也是最高的) 所以可以使用如下命令:
    curl http://localhost:6800/schedule.json -d project=XXX -d spider=XXX -d setting=FEED_URI=file:/Users/XXX/out/%\(name\)s/%\(time\)s.json -d setting=FEED_FORMAT=jsonlines -d setting=FEED_EXPORT_ENCODING=utf-8
    就能实现用默认jsonlines管道输出到指定目录 :mrgreen:
    受到博主文章的启发 我也畅想一下 是不是可以通过替换portia输出scrapy的模版 将其复用scrapy-redis的组件 从而实现自动部署可视化分布式爬虫呢

    • bruce

      666 联想的不错,然后可以使用elk 里面的 logstash 自动收集入库到es 里面,这样也满不错的,scrapy-redis 是驻留模式的,可以考虑将规则也存入到redis 里面,爬虫拿到规则就直接执行。

      • Lam

        大神真是字字珠玑 :cry: 我之前设想是把数据收集起来再集中解析 但这样就没法利用每个丛机的处理能力 就是分布式的wget 没想到还可以把规则存到redis 真是醍醐灌顶

        • bruce

          规则需要持久化在一个稳定的数据库里面,比如mysql 里面,不然一当机就规则全消失了,这还涉及到一个规则的同步问题,总之长久的规则需要有一种方式持久化保存起来。 :razz:

          • Lam

            所言极是,昨天说到将解析规则一起存到redis 我设想有两种方案 一种是把url和解析规则捆绑成一条数据 这样虽然可以保持解析规则与url的一致性 但是redis的数据读写量会很大 另一种是单独把解析规则按task_id构建键值存入redis spider每次解析response还是要访问redis 依然会增加redis负荷 而在从机持久化地存储解析规则就需要额外维护一个数据库或者配置文件 redis只需要用来共享待爬队列就可以了

          • bruce

            这个方式是可行的,有一些类似配置的爬虫就是采用这种方式来爬取的 ,666