利用scrapy和MongoDB来开发一个爬虫
2016-05-22 22:45
435 查看
今天我们利用scrapy框架来抓取Stack Overflow里面最新的问题(问题标题和网址),并且将这些问题保存到MongoDb当中,直接提供给客户进行查询。
$ pip install Scrapy
一旦安装完成之后你可以直接在python shell当中输入下面的命令,倘若没有出现错误的话,说明已安装完成
>>> import scrapy
>>>
brew install mongodb
运行mongodb同样特别的简单,只需要在终端下面输入下面的语法:
mongod --dbpath=.
--dbpath是指定数据库存放的路径,运行之后会在该路径下面生成一些文件
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/861973d97f359b2d985de0f8fc818ca0.png)

下一步我们就需要安装PyMongo,同样采用pip的方式
$ pip install pymongo
$ scrapy startproject stack
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/584d2f302f0255995bc564cc545578cd.png)

一旦上面的命令完成之后,scrapy会直接创建相应的文件,这些文件包含了基本的信息,便于你来修改相应的内容。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/88efabd083808ec8707f6dd764e06e8f.png)

有关StackItem()预定义时并让其继承于scrapy.Item
这里我们需要在里面添加两个字段,分别用来存放抓取到的标题以及链接
name 是定义爬虫的名称
allowed_domains 指定爬虫进行爬取的域地址
start_urls 定义爬虫需要抓取的网页的url地址
<div class='content'>
下面我们通过chrome来讲解如果找到xpath的路径 ,在进行操作之前我们需要打开开发者工具,可以点击菜单栏上面的视图->开发者->开发者工具来打进入开发者模式,或者可以根据快捷捷来进行打开。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/01b39e05eb26b6fafad60e4d017bd21a.png)

打开之后我们在需要的内容上面点击右击会弹出一个菜单,这里我们可以选择检查来找到当前的内容在html相应的位置
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/56587409a44cce57e312d0e99e3c920b.png)

这里chrome会自动帮助我们找到相应的位置,通过下面的分析,我们知道标题的路径是包含在一个下面的h3标记当中。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/32001475342c8bd34a6c13d4c917a2d3.png)

现在我们来更新相应的stack_spider.py脚本
通过遍历所有的符合//div[@class="summary"]/h3的元素,并且从中找到我们真正需要爬取的元素内容
scrapy crawl stack
现在我们需要将爬取到的所有的信息保存到一个文件当中,可以在后面添加二个参数-o和-t
scrapy crawl stack -o items.json -t json
下面是实际保存的文件的内容分别包含了title和url
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/2c4079f35c7b3ade7c18d34b738b834e.png)

在进行操作之前我们需要在setinngs.py指定相应的pipeline和添加一些数据库的参数
在上面我们已经定义了数据库的参数,现在我们终于派上用场了。
上面的代码是我们创建了一个MongoDBPipeline()的类,以及定义初始化函数,用来读取刚才的参数来创建一个Mongo的连接。
上面已经完成了对数据的连接,以及相应数据的存储
$ scrapy crawl stack
当内容执行完成之后没有出现任何的错误的提示,恭喜你已经将数据正确的存入到mongodb当中。
这里我们通过Robomongo来访问数据库的时候发现创建了一个stackoverflow的数据库,下面已经成功创建了一个名为questions的Collections.并且已经存入了相应的数据了。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/8d438ade6c20843cf5bc1f34f264997b.png)

安装
在进行今天的任务之前我们需要安装二个框架,分别是Scrapy (1.1.0)和pymongo (3.2.2).scrapy
如果你运行的的系统是osx或者linux,可以直接通过pip进行安装,而windows需要另外安装一些依赖,因为电脑的原因不对此进行讲解。$ pip install Scrapy
一旦安装完成之后你可以直接在python shell当中输入下面的命令,倘若没有出现错误的话,说明已安装完成
>>> import scrapy
>>>
安装PyMongo和mongodb
因为系统是osx的,所以直接通过下面的语句就可以安装。brew install mongodb
运行mongodb同样特别的简单,只需要在终端下面输入下面的语法:
mongod --dbpath=.
--dbpath是指定数据库存放的路径,运行之后会在该路径下面生成一些文件
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/861973d97f359b2d985de0f8fc818ca0.png)

下一步我们就需要安装PyMongo,同样采用pip的方式
$ pip install pymongo
Scrapy 项目
我们来创建一个新的scrapy的项目,在终端输入下面的语法$ scrapy startproject stack
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/584d2f302f0255995bc564cc545578cd.png)

一旦上面的命令完成之后,scrapy会直接创建相应的文件,这些文件包含了基本的信息,便于你来修改相应的内容。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/88efabd083808ec8707f6dd764e06e8f.png)

定义数据
items.py文件用于我们定义需要抓取对象的存储的“容器“有关StackItem()预定义时并让其继承于scrapy.Item
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html import scrapy class StackItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() pass
这里我们需要在里面添加两个字段,分别用来存放抓取到的标题以及链接
from scrapy.item import Item,Field class StackItem(Item): # define the fields for your item here like: title=Field() url=Field()
创建爬虫
我们需要在spider文件夹下面创建一个stack_spider.py的文件,这个里面包容我们爬虫进行抓取时的行为。就是告诉爬虫我们需要抓取哪些内容以及内容的来源。from scrapy import Spider from scrapy.selector import Selector from stack.items import StackItem class StackSpider(Spider): name="stack" allowed_domains=['stackoverflow.com'] start_urls = [ "http://stackoverflow.com/questions?pagesize=50&sort=newest", ]
name 是定义爬虫的名称
allowed_domains 指定爬虫进行爬取的域地址
start_urls 定义爬虫需要抓取的网页的url地址
XPath 选择
scrapy使用XPath来进行匹配相应的数据的来源,html是一种标记的语法,里面定义了很多的标签和属性,比如说我们定义一个下面的这样的一个标签,这里我们就可以通过'//div[@class="content"]'来找到这个标记,找到之后我们可以取出其中的属性或者它的子节点<div class='content'>
下面我们通过chrome来讲解如果找到xpath的路径 ,在进行操作之前我们需要打开开发者工具,可以点击菜单栏上面的视图->开发者->开发者工具来打进入开发者模式,或者可以根据快捷捷来进行打开。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/01b39e05eb26b6fafad60e4d017bd21a.png)

打开之后我们在需要的内容上面点击右击会弹出一个菜单,这里我们可以选择检查来找到当前的内容在html相应的位置
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/56587409a44cce57e312d0e99e3c920b.png)

这里chrome会自动帮助我们找到相应的位置,通过下面的分析,我们知道标题的路径是包含在一个下面的h3标记当中。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/32001475342c8bd34a6c13d4c917a2d3.png)

现在我们来更新相应的stack_spider.py脚本
from scrapy import Spider from scrapy.selector import Selector from stack.items import StackItem class StackSpider(Spider): name="stack" allowed_domains=['stackoverflow.com'] start_urls = [ "http://stackoverflow.com/questions?pagesize=50&sort=newest", ] def parse(self,response): questions=Selector(response).xpath('//div[@class="summary"]/h3')
提取数据
创建抓取的规约之后,我们需要与刚才创建的items实体进行关联,我们继续修改stack_spider.py文件from scrapy import Spider from scrapy.selector import Selector from stack.items import StackItem class StackSpider(Spider): name="stack" allowed_domains=['stackoverflow.com'] start_urls = [ "http://stackoverflow.com/questions?pagesize=50&sort=newest", ] def parse(self,response): questions=Selector(response).xpath('//div[@class="summary"]/h3') for question in questions: item=StackItem() item['title'] = question.xpath( 'a[@class="question-hyperlink"]/text()').extract()[0] item['url'] = question.xpath( 'a[@class="question-hyperlink"]/@href').extract()[0] yield item
通过遍历所有的符合//div[@class="summary"]/h3的元素,并且从中找到我们真正需要爬取的元素内容
测试
现在我们进行测试,只要在项目的目录下面运行以下的脚本就可以进行测试 。scrapy crawl stack
现在我们需要将爬取到的所有的信息保存到一个文件当中,可以在后面添加二个参数-o和-t
scrapy crawl stack -o items.json -t json
下面是实际保存的文件的内容分别包含了title和url
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/2c4079f35c7b3ade7c18d34b738b834e.png)

将元素存放入MongoDB
这里我们需要将所有的元素保存到Mongodb collection当中。在进行操作之前我们需要在setinngs.py指定相应的pipeline和添加一些数据库的参数
ITEM_PIPELINES = { 'stack.pipelines.MongoDBPipeline': 300, } MONGODB_SERVER = "localhost" MONGODB_PORT = 27017 MONGODB_DB = "stackoverflow" MONGODB_COLLECTION = "questions"
pipeline 管理
在之前的步骤里面我们分别已经完成了对html的解析,以及指定数据的存储。但是这时所有的信息都在内存当中,我们需要将这些爬取到数据存储到数据库当中,这里就轮到pipelines.py上场了,这玩意就负责对数据的存储的。在上面我们已经定义了数据库的参数,现在我们终于派上用场了。
import pymongo from scrapy.conf import settings from scrapy.exceptions import DropItem from scrapy import log class MongoDBPipeline(object): def __init__(self): connection=pymongo.MongoClient( settings['MONGODB_SERVER'], settings['MONGODB_PORT'] ) db=connection[settings['MONGODB_DB']] self.collection=db[settings['MONGODB_COLLECTION']]
上面的代码是我们创建了一个MongoDBPipeline()的类,以及定义初始化函数,用来读取刚才的参数来创建一个Mongo的连接。
数据处理
下一步我们需要定义一个函数来处理解析的数据# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymongo from scrapy.conf import settings from scrapy.exceptions import DropItem from scrapy import log class MongoDBPipeline(object): def __init__(self): connection=pymongo.MongoClient( settings['MONGODB_SERVER'], settings['MONGODB_PORT'] ) db=connection[settings['MONGODB_DB']] self.collection=db[settings['MONGODB_COLLECTION']] def process_item(self,item,spider): valid=True for data in item: if not data: valid=False raise DropItem('Missing{0}!'.format(data)) if valid: self.collection.insert(dict(item)) log.msg('question added to mongodb database!', level=log.DEBUG,spider=spider) return item
上面已经完成了对数据的连接,以及相应数据的存储
测试
我们同样在stack目录当中运行下面的命令$ scrapy crawl stack
当内容执行完成之后没有出现任何的错误的提示,恭喜你已经将数据正确的存入到mongodb当中。
这里我们通过Robomongo来访问数据库的时候发现创建了一个stackoverflow的数据库,下面已经成功创建了一个名为questions的Collections.并且已经存入了相应的数据了。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202001/22/8d438ade6c20843cf5bc1f34f264997b.png)

相关文章推荐
- mongodb基础-索引
- nodejs和mongodb实践
- centos7 下安装MongoDB
- MongoDB简单入门
- mongodb+springmvc+spring+maven配置
- MongoDb的接口使用(Java版本)
- linux下安装mongodb
- mongodb数据库实践笔记
- linux mongodb 安装、自启动
- mongoVUE 连接MongoDB3.2.2不能正常显示collection的问题
- Mongodb中的ObjectId浅谈
- Mongodb中数据聚合之聚合管道aggregate
- nodejs+express+mongodb搭建网站
- mongodb高级操作(2)-查询
- MongoDB服务无法启动,发生服务特定错误:100
- 学习MongoDB 十: MongoDB聚合(Map-Reduce)(二)
- Hive连接MongoDB
- Mongodb 启动报错:"/sys/kernel/mm/transparent_hugepage/enabled is 'always'"
- MacBook系统下的mongodb安装和使用
- MongoDB相关资料收集