scrapy 入门

  • 2017-02-17 20:19:10
  • 2602
  • 0

了解、学习新的IT技术, 老方法:有定义则先从定义入手;其次分析理解定义,思考应用场景;了解、学习已有使用案例,并与预设想的场景对比。另外,了解新事物的历史也是非常有必要的。

一、定义:

Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。其最初是为了 页面抓取 (更确切来说是网络抓取 )所设计的, 也可以应用在获取API所返回的数据(例如 Amazon Associates Web Services ) 或者通用的网络爬虫。

二、解释:

从定义中,可以提取中一下几点重要信息:

1、应用框架

       应用:是相对于”理论“而言,可以方便被使用、应用。

       框架:IT语境中的框架,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构。在此结构上可以根据具体问题扩展、安插更多的组成部分,从而更迅速和方便地构建完整的解决问题的方案。可以初步猜想此框架还是属于web 框架范畴,框架原理还是基于MVC,但考虑到该框架是用来做爬虫的,所以它主要是偏重于M和C层的。

2、爬取网站数据

      为该框架的核心功能,底层用到的应该是urllib和urllib2模块。但作为一个爬虫框架还应该可以轻松配置发送多并发web请求的,配置各种特有功能中间件等,设置请求cookie、请求头、缓存等等,爬虫状态监测及获取、异常处理等等。

3、提取结构性数据

     关于提取结构性数据这块,python已有组件如:beautifulsoup,xml。可以设想在分析结构性数据这块时,scrapy可能既会保留对beautifulsoup、xml调用的支持,也有可能自己写一套解析模块。

​三、知识过渡与整体理解:

Items:爬取的主要目标就是从非结构性的数据源提取结构性数据,Item就是用来保存爬取到的结构性数据的容器,数据类型为python的dict

Spider:简而言之,就是定义爬取的动作及分析某个网页(或者部分网页)的地方。

​Selectors:称作选择器(seletors),是指通过特定的 XPath 或者 CSS 表达式来“选择” HTML文件中的某个部分。

Item Pipeline​:当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。

​与web框架概念对比:

 

ScrapyItemsSpiderselectorsItem Pipeline
web框架models(M层)views(视图控制函数)model中的field值类似于models中对应的save函数

四、举例:

就拿自己做过的一个项目举例吧。

大致需求是:获取同行业网站的所有产品以及产品下面的评论,并提取对应产品的标题以及评论中的关键词(主要为名词和形容),最后将数据存储到mongodb中。

​思路以及需求分析:

​1、获取产品数据:首先从首页出发, 通过发现大多数电商类网站首页必有各种分类展示。因此可以从首页的这些分类一一着手去爬取所有产品。

​2、获取评论:可以在产品详情页面获取产品信息时,同时得到该产品的评论信息。

​3、获取标题以及评论中的关键词:可通过nltk模块,不过nltk模块安装稍微有点麻烦,后面会有介绍。

​4、存储到mongodb:通过模块pymongo并结合item Pipeline,写一个pipeline类即可。

​5、注意:处理产品列表以及评论列表的多页抓取。

对应实现方法

​1、首先获取产品数据这块不难,最基本的爬虫功能就能实现,只要做过官网的dirbot项目应该都会,因此可以先把相关的items写好,这一步好比数据库设计。

​2、获取评论一般可以通过页面的css 的id或者class标签来得到页面的评论区域。

​3、关于nltk的安装以及获取名词与形容词的代码:

​nltk的安装:

pip install nltk
python -m nltk.downloader averaged_perceptron_tagger punkt maxent_treebank_pos_tagger 
注:nltk的包很多也很大,要满足以上需求,安装这三个包即可:averaged_perceptron_tagger punkt maxent_treebank_pos_tagger

通过nltk获取一段字符串中的名词与形容词:

def get_nouns_and_adjs(title):
    """
    获取名词和形容词
    """
    results = []
    title_list = nltk.word_tokenize(title.lower())
    tag_words = nltk.pos_tag(title_list)
    for word, tag in tag_words:
        if tag.startswith(('NN', 'JJ')):
            results.append(word)
    return results

​4、存储到mongodb的Item Pipline类代码:

import datetime
import pymongo


class MongoPipeline(object):

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db
        today = datetime.date.today()
        datetime_str = today.strftime("%Y%m%d")
        self.mongo_col = "tag_items_%s" % datetime_str

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'tag_stat'),
        )

    def open_spider(self, spider):
        if self.mongo_uri:
            self.client = pymongo.MongoClient(self.mongo_uri)
        else:
            self.client = pymongo.MongoClient()
        self.db = self.client[self.mongo_db]
        # print spider.name
        self.collection = self.db[self.mongo_col]
        self.collection.create_index([("domain", pymongo.ASCENDING),
                                     ("cloth_name", pymongo.ASCENDING),
                                     ("tag_name", pymongo.ASCENDING),
                                     ("hotwords.wordname", pymongo.ASCENDING)])

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):

        self.collection.insert(dict(item))
        return item


发表评论

* *