一文搞懂Scrapy与MongoDB交互过程
在使用Scrapy进行数据爬取的过程中,我们经常需要将爬取下来的数据存储到数据库中。MongoDB是一个非常流行的NoSQL数据库,它与Scrapy的交互非常方便。本文将介绍如何在Scrapy中使用MongoDB进行数据存储。
安装MongoDB
在使用MongoDB之前,需要先安装MongoDB数据库。可以通过MongoDB官网下载相应版本的MongoDB,并进行安装。安装完毕后,可以通过命令行启动MongoDB服务:
$ mongod
安装pymongo
Scrapy使用pymongo来与MongoDB进行交互,因此需要先安装pymongo。可以通过pip进行安装:
$ pip install pymongo
配置MongoDB Pipeline
配置Scrapy的Pipeline可以将爬取的数据存储到MongoDB中。需要在Scrapy项目中创建一个Pipeline,并在settings.py
文件中进行配置。
在Scrapy项目中创建一个名为MongoDBPipeline
的新文件,并添加以下内容:
import pymongo
class MongoDBPipeline(object):
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
collection_name = item.__class__.__name__
self.db[collection_name].insert(dict(item))
return item
在settings.py
中添加以下内容:
ITEM_PIPELINES = {
'myproject.pipelines.MongoDBPipeline': 300,
}
MONGO_URI = 'mongodb://localhost:27017/'
MONGO_DATABASE = 'items'
在上述代码中,我们定义了一个名为MongoDBPipeline
的Pipeline。在process_item
方法中,我们将爬取的数据存储到MongoDB中。默认情况下,每个爬虫CrawlSpider中的每个Item子类都会被存储到自己的集合中。例如,如果我们有一个名为MyItem
的Item类,则数据将被存储在MongoDB的myitem
集合中。
在settings.py
中,我们将MongoDBPipeline
添加到ITEM_PIPELINES
中,并设置了MongoDB的连接地址和数据库名称。
使用MongoDB Pipeline
在Spider中使用MongoDB Pipeline非常简单。只需将要存储的数据传递给Pipeline,Pipeline将自动将数据存储到MongoDB中。
以下是一个示例:
import scrapy
from myproject.items import MyItem
class MySpider(scrapy.Spider):
name = 'myspider'
def start_requests(self):
yield scrapy.Request('https://www.example.com', self.parse)
def parse(self, response):
item = MyItem()
item['name'] = 'example'
item['url'] = response.url
yield item
在上述代码中,我们定义了一个名为MySpider
的Spider。在parse
方法中,我们创建了一个名为MyItem
的新Item,并将它的name
字段和url
字段设置为了固定值。这个Item将会被传递给Pipeline进行存储。
示例一
下面我们通过一个具体的示例来演示如何使用Scrapy和MongoDB进行数据交互。
假设我们要从豆瓣电影中爬取正在热映的电影信息,并将电影的标题、评分、导演、主演和封面链接保存到MongoDB中。
首先,创建一个新的Scrapy项目:
$ scrapy startproject doubanmovie
在项目中创建一个新的名为movies.py
的Spider:
import scrapy
from doubanmovie.items import DoubanmovieItem
class MoviesSpider(scrapy.Spider):
name = 'movies'
allowed_domains = ['movie.douban.com']
start_urls = ['https://movie.douban.com/']
def parse(self, response):
movie_links = response.xpath('//div[@id="screening"]//a[@data-psource]/@href')
for link in movie_links:
yield scrapy.Request(link.extract(), callback=self.parse_movie)
def parse_movie(self, response):
item = DoubanmovieItem()
item['title'] = response.xpath('//h1/span/text()').extract_first()
item['score'] = response.xpath('//strong[@class="rating_num"]/text()').extract_first()
item['directors'] = response.xpath('//span[contains(text(),"导演")]/following-sibling::span/a/text()').extract()
item['stars'] = response.xpath('//span[contains(text(),"主演")]/following-sibling::span/a/text()').extract()
item['image_url'] = response.xpath('//img[@rel="v:image"]/@src').extract_first()
yield item
在上述代码中,我们定义了一个名为MoviesSpider
的Spider,在parse
方法中解析正在热映的电影页面,并将每个电影的详情页面链接传递给parse_movie
方法。在parse_movie
方法中,我们解析了电影详情页面中的电影标题、评分、导演、主演和封面链接,并将它们保存到一个新的名为DoubanmovieItem
的Item中。
接下来,创建一个新的Pipeline,并将它配置到settings.py
中:
import pymongo
class MongoDBPipeline(object):
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
collection_name = item.__class__.__name__
self.db[collection_name].insert(dict(item))
return item
在settings.py
中添加以下内容:
ITEM_PIPELINES = {
'doubanmovie.pipelines.MongoDBPipeline': 300,
}
MONGO_URI = 'mongodb://localhost:27017/'
MONGO_DATABASE = 'doubanmovie'
在上述代码中,我们将Pipeline的名称设置为了doubanmovie.pipelines.MongoDBPipeline
,将MongoDB的连接地址设置为了mongodb://localhost:27017/
,将数据库名称设置为了doubanmovie
。
最后,运行这个Spider:
$ scrapy crawl movies
Spider将会将爬取到的电影信息存储到MongoDB中。可以在MongoDB的命令行中使用以下命令查询保存的数据:
$ mongo
> use doubanmovie
> db.doubanmovieitem.find()
示例二
下面我们再通过一个示例来演示如何在Scrapy中使用MongoDB进行数据存储。
假设我们要从某个电商网站爬取iPhone的信息,并将名称、价格、尺寸和颜色保存到MongoDB中。
首先,创建一个新的Scrapy项目:
$ scrapy startproject iphone
在项目中创建一个新的名为phones.py
的Spider:
import scrapy
from iphone.items import IphoneItem
class PhonesSpider(scrapy.Spider):
name = 'phones'
allowed_domains = ['example.com']
start_urls = ['https://www.example.com/phones/']
def parse(self, response):
phone_links = response.xpath('//a[contains(@href,"/iphone/")]')
for link in phone_links:
yield scrapy.Request(link.xpath('@href').extract_first(), callback=self.parse_phone)
def parse_phone(self, response):
item = IphoneItem()
item['name'] = response.xpath('//h1/text()').extract_first()
item['price'] = response.xpath('//span[@class="price"]/text()').extract_first()
item['size'] = response.xpath('//dt[text()="尺寸"]/following-sibling::dd/text()').extract_first()
item['color'] = response.xpath('//dt[text()="颜色"]/following-sibling::dd/text()').extract_first()
yield item
在上述代码中,我们定义了一个名为PhonesSpider
的Spider,在parse
方法中解析电商网站的iPhone页面,并将每个iPhone的详情页面链接传递给parse_phone
方法。在parse_phone
方法中,我们解析了iPhone详情页面中的名称、价格、尺寸和颜色,并将它们保存到一个新的名为IphoneItem
的Item中。
接下来,创建一个新的Pipeline,并将它配置到settings.py
中:
import pymongo
class MongoDBPipeline(object):
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DATABASE', 'items')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
collection_name = item.__class__.__name__
self.db[collection_name].insert(dict(item))
return item
在settings.py
中添加以下内容:
ITEM_PIPELINES = {
'iphone.pipelines.MongoDBPipeline': 300,
}
MONGO_URI = 'mongodb://localhost:27017/'
MONGO_DATABASE = 'phone'
在上述代码中,我们将Pipeline的名称设置为了iphone.pipelines.MongoDBPipeline
,将MongoDB的连接地址设置为了mongodb://localhost:27017/
,将数据库名称设置为了phone
。
最后,运行这个Spider:
$ scrapy crawl phones
Spider将会将爬取到的iPhone信息存储到MongoDB中。可以在MongoDB的命令行中使用以下命令查询保存的数据:
$ mongo
> use phone
> db.iphoneitem.find()
至此,我们已经成功实现了在Scrapy中使用MongoDB进行数据存储。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文搞懂Scrapy与MongoDB交互过程 - Python技术站