python爬虫框架scrapy的简单示例

对python这个高级语言感兴趣的小伙伴,下面一起跟随编程之家 jb51.cc的小编两巴掌来看看吧!

生成项目

scrapy提供一个工具来生成项目,生成的项目中预置了一些文件用户需要在这文件添加自己的代码

打开命令行,执行:scrapy startproject tutorial,生成的项目类似下面的结构

tutorial/

scrapy.cfg

tutorial/

__init__.py

items.py

pipelines.py

settings.py

spiders/

__init__.py

...

scrapy.cfg是项目的配置文件

用户自己写的spider要放在spiders目录下面,一个spider类似


# @param Python爬虫框架scrapy实例详解
# @author 编程之家 jb51.cc|jb51.cc 

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)

# End www.jb51.cc

name属性很重要,不同spider不能使用相同的name

start_urls是spider抓取网页的起始点,可以包括多个url

parse方法是spider抓到一个网页以后调用的callback,避免使用这个名字来定义自己的方法

当spider拿到url的内容以后,会调用parse方法,并且传递一个response参数给它,response包含了抓到的网页的内容,在parse方法里,你可以从抓到的网页里面解析数据。上面的代码只是简单地把网页内容保存到文件

 

开始抓取

你可以打开命令行,进入生成的项目根目录tutorial/,执行 scrapy crawl dmoz, dmoz是spider的name。

 

解析网页内容

scrapy提供了方便的办法从网页中解析数据,这需要使用到HtmlXPathSelector


# @param Python爬虫框架scrapy实例详解
# @author 编程之家 jb51.cc|jb51.cc 

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/,response):
        hxs = HtmlXPathSelector(response)
        sites = hxs.select('//ul/li')
        for site in sites:
            title = site.select('a/text()').extract()
            link = site.select('a/@href').extract()
            desc = site.select('text()').extract()
            print title,link,desc

# End www.jb51.cc

HtmlXPathSelector使用了Xpath来解析数据

//ul/li表示选择所有的ul标签下的li标签

a/@href表示选择所有a标签的href属性

a/text()表示选择a标签文本

a[@href=abc]表示选择所有href属性是abc的a标签

我们可以把解析出来的数据保存在一个scrapy可以使用的对象中,然后scrapy可以帮助我们把这些对象保存起来,而不用我们自己把这些数据存到文件中。我们需要在items.py中添加一些类,这些类用来描述我们要保存的数据

from scrapy.item import Item,Field

class DmozItem(Item):

title = Field()

link = Field()

desc = Field()

然后在spider的parse方法中,我们把解析出来的数据保存在DomzItem对象中。


# @param Python爬虫框架scrapy实例详解
# @author 编程之家 jb51.cc|jb51.cc 

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.select('//ul/li')
       items = []
       for site in sites:
           item = DmozItem()
           item['title'] = site.select('a/text()').extract()
           item['link'] = site.select('a/@href').extract()
           item['desc'] = site.select('text()').extract()
           items.append(item)
       return items

# End www.jb51.cc

在命令行执行scrapy的时候,我们可以加两个参数,让scrapy把parse方法返回的items输出到json文件

scrapy crawl dmoz -o items.json -t json

items.json会被放在项目的根目录

 

让scrapy自动抓取网页上的所有链接

上面的示例中scrapy只抓取了start_urls里面的两个url的内容,但是通常我们想实现的是scrapy自动发现一个网页上的所有链接,然后再去抓取这些链接内容。为了实现这一点我们可以在parse方法里面提取我们需要的链接,然后构造一些Request对象,并且把他们返回,scrapy会自动的去抓取这些链接代码类似:


# @param Python爬虫框架scrapy实例详解
# @author 编程之家 jb51.cc|jb51.cc 

class MySpider(BaseSpider):
    name = 'myspider'
    start_urls = (
        'http://example.com/page1','http://example.com/page2',)
    def parse(self,response):
        # collect `item_urls`
        for item_url in item_urls:
            yield Request(url=item_url,callback=self.parse_item)
    def parse_item(self,response):
        item = MyItem()
        # populate `item` fields
        yield Request(url=item_details_url,Meta={'item': item},callback=self.parse_details)
    def parse_details(self,response):
        item = response.Meta['item']
        # populate more `item` fields
        return item

# End www.jb51.cc

 

parse是认的callback,它返回了一个Request列表,scrapy自动的根据这个列表抓取网页,每当抓到一个网页,就会调用parse_item,parse_item也会返回一个列表,scrapy又会根据这个列表去抓网页,并且抓到后调用parse_details

为了让这样的工作更容易,scrapy提供了另一个spider基类,利用它我们可以方便的实现自动抓取链接. 我们要用到CrawlSpider


# @param Python爬虫框架scrapy实例详解
# @author 编程之家 jb51.cc|jb51.cc 

from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
class MininovaSpider(CrawlSpider):
    name = 'mininova.org'
    allowed_domains = ['mininova.org']
    start_urls = ['http://www.mininova.org/today']
    rules = [Rule(SgmlLinkExtractor(allow=['/tor/\d+'])),Rule(SgmlLinkExtractor(allow=['/abc/\d+']),'parse_torrent')]
    def parse_torrent(self,response):
        x = HtmlXPathSelector(response)
        torrent = TorrentItem()
        torrent['url'] = response.url
        torrent['name'] = x.select(//h1/text()).extract()
        torrent['description'] = x.select(//div[@id='description']).extract()
        torrent['size'] = x.select(//div[@id='info-left']/p[2]/text()[2]).extract()
        return torrent

# End www.jb51.cc

相比BaseSpider,新的类多了一个rules属性,这个属性一个列表,它可以包含多个Rule,每个Rule描述了哪些链接需要抓取,哪些不需要。这是Rule类的文档http://doc.scrapy.org/en/latest/topics/spiders.html#scrapy.contrib.spiders.Rule

这些rule可以有callback,也可以没有,当没有callback的时候,scrapy简单的follow所有这些链接.

pipelines.py的使用

在pipelines.py中我们可以添加一些类来过滤掉我们不想要的item,把item保存到数据库


# @param Python爬虫框架scrapy实例详解
# @author 编程之家 jb51.cc|jb51.cc 

from scrapy.exceptions import DropItem
class FilterWordsPipeline(object):
    A pipeline for filtering out items which contain certain words in their
    description
    # put all words in lowercase
    words_to_filter = ['politics','religion']
    def process_item(self,item,spider):
        for word in self.words_to_filter:
            if word in unicode(item['description']).lower():
                raise DropItem(Contains forbidden word: %s % word)
        else:
            return item

# End www.jb51.cc

如果item不符合要求,那么就抛一个异常,这个item不会被输出到json文件中。

要使用pipelines,我们还需要修改settings.py

添加一行

ITEM_PIPELInes = ['dirbot.pipelines.FilterWordsPipeline']

现在执行scrapy crawl dmoz -o items.json -t json,不符合要求的item就被过滤掉了

相关文章

功能概要:(目前已实现功能)公共展示部分:1.网站首页展示...
大体上把Python中的数据类型分为如下几类: Number(数字) ...
开发之前第一步,就是构造整个的项目结构。这就好比作一幅画...
源码编译方式安装Apache首先下载Apache源码压缩包,地址为ht...
前面说完了此项目的创建及数据模型设计的过程。如果未看过,...
python中常用的写爬虫的库有urllib2、requests,对于大多数比...