Scrapy入门

什么是Scrapy

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

scrapy使用了 Twisted异步网络库来处理网络通讯。整体架构大致如下

Scrapy主要包括了以下组件:

  • 引擎(Scrapy): 用来处理整个系统的数据流处理, 触发事务(框架核心)
  • 调度器(Scheduler): 用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
  • 下载器(Downloader): 用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
  • 爬虫(Spiders): 爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
  • 项目管道(Pipeline): 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
  • 下载器中间件(Downloader Middlewares): 位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
  • 爬虫中间件(Spider Middlewares): 介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
  • 调度中间件(Scheduler Middewares): 介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

Scrapy运行流程大概如下:

  1. 首先,引擎从调度器中取出一个链接(URL)用于接下来的抓取
  2. 引擎把URL封装成一个请求(Request)传给下载器,下载器把资源下载下来,并封装成应答包(Response)
  3. 然后,爬虫解析Response
  4. 若是解析出实体(Item),则交给实体管道进行进一步的处理。
  5. 若是解析出的是链接(URL),则把URL交给Scheduler等待抓取。



本教程主要内容包括一下四步:

1. 创建一个新的Scrapy Project
2. 定义你需要从网页中提取的元素Item
3. 实现一个Spider类,通过接口完成爬取URL和提取Item的功能
4. 实现一个Item PipeLine类,完成Item的存储功能

新建工程

首先,为我们的爬虫新建一个工程,首先进入一个目录(任意一个我们用来保存代码的目录),执行:

  scrapy startproject Domz

    进入到Domz目录下,查看目录结构:

  C:\Users\xian\Desktop\Domz>tree /f

    看到的目录结构如下:

    文件夹 PATH 列表
    卷序列号为 00000200 760C:AAD6
    C:.
    │  scrapy.cfg
    │
    └─Domz
        │  items.py
        │  pipelines.py
        │  settings.py
        │  __init__.py
        │
        └─spiders
                __init__.py
scrapy.cfg: 项目配置文件
items.py: 需要提取的数据结构定义文件
pipelines.py: 管道定义,用来对items里面提取的数据做进一步处理,如保存等
settings.py: 爬虫配置文件
spiders: 放置spider的目录

定义Item

在items.py里面定义我们要抓取的数据:

from scrapy.item import Item, Field
 
class DmozItem(Item):
   title = Field()
   link = Field()
   desc = Field()
这里我们需要获取dmoz页面上的标题,链接,描述,所以定义一个对应的items结构,不像Django里面models的定义有那么多种类的Field,这里只有一种就叫Field(),再复杂就是Field可以接受一个default值。

实现Spider

spider只是一个继承字scrapy.spider.BaseSpider的Python类,有三个必需的定义的成员

name: 名字,这个spider的标识
start_urls: 一个url列表,spider从这些网页开始抓取
parse(): 一个方法,当start_urls里面的网页抓取下来之后需要调用这个方法解析网页内容,同时需要返回下一个需要抓取的网页,或者返回items列表

所以在spiders目录下新建一个spider,dmoz_spider.py:

from scrapy.spider import BaseSpider

class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
    ]

    def parse(self, response):
        filename = response.url.split("/")[-2]
        open(filename, 'wb').write(response.body)

提取Item

提取数据到Items里面,主要用到XPath提取网页数据:

scrapy有提供两个XPath选择器,HtmlXPathSelector和XmlXPathSelector,一个用于HTML,一个用于XML,XPath选择器有三个方法

select(xpath): 返回一个相对于当前选中节点的选择器列表(一个XPath可能选到多个节点)
extract(): 返回选择器(列表)对应的节点的字符串(列表)
re(regex): 返回正则表达式匹配的字符串(分组匹配)列表
一种很好的方法是在Shell里面对XPath进行测试:

scrapy shell http://www.dmoz.org/Computers/Programming/Languages/Python/Books/

现在修改parse()方法看看如何提取数据到items里面去:

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector

class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
]    
  
    def parse(self, response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.path('//fieldset/ul/li')
        #sites = hxs.path('//ul/li')
        for site in sites:
            title = site.path('a/text()').extract()
            link = site.path('a/@href').extract()
            desc = site.path('text()').extract()
            #print title, link, desc
            print title, link

现在我们再次抓取dmoz.org,你将看到站点在输出中被打印 ,cmd运行命令:

scrapy crawl dmoz

使用条目(Item)

Item 对象是自定义的python字典,使用标准字典类似的语法,你可以获取某个字段(即之前定义的类的属性)的值:

>>> item = DmozItem() 
>>> item['title'] = 'Example title' 
>>> item['title'] 
'Example title' 

Spiders希望将其抓取的数据存放到Item对象中。为了返回我们抓取数据,spider的最终代码应当是这样:

from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector

from tutorial.items import DmozItem

class DmozSpider(BaseSpider):
   name = "dmoz"
   allowed_domains = ["dmoz.org"]
   start_urls = [
       "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
       "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
   ]

   def parse(self, response):
       hxs = HtmlXPathSelector(response)
       sites = hxs.path('//fieldset/ul/li')
       #sites = hxs.path('//ul/li')
       items = []
       for site in sites:
           item = DmozItem()
           item['title'] = site.path('a/text()').extract()
           item['link'] = site.path('a/@href').extract()
           item['desc'] = site.path('text()').extract()
           items.append(item)
       return items

保存抓取的数据

保存信息的最简单的方法是通过Feed exports,命令如下:

scrapy crawl dmoz -o items.json -t json

所有抓取的items将以JSON格式被保存在新生成的items.json 文件中

在像本教程一样的小型项目中,这些已经足够。然而,如果你想用抓取的items做更复杂的事情,你可以写一个 Item Pipeline(条目管道)。因为在项目创建的时候,一个专门用于条目管道的占位符文件已经随着items一起被建立,目录在tutorial/pipelines.py。如果你只需要存取这些抓取后的items的话,就不需要去实现任何的条目管道。

实现PipeLine

PipeLine用来对Spider返回的Item列表进行保存操作,可以写入到文件、或者数据库等。

PipeLine只有一个需要实现的方法:process_item,例如我们将Item保存到一个文件中:

def __init__(self):
    self.file = open('jingdong.txt', 'wb')
 
def process_item(self, item, spider):
    self.file.write(item['title'] + '\t'+ item['link'] + '\t' + item['desc']+'\n')
到现在,我们就完成了一个基本的爬虫的实现。

参考 http://www.icodelogic.com/?p=441

http://www.cnblogs.com/txw1958/archive/2012/07/16/scrapy-tutorial.html








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值