python爬虫框架scrapy实例详解
当前位置:以往代写 > Python教程 >python爬虫框架scrapy实例详解
2019-06-14

python爬虫框架scrapy实例详解

python爬虫框架scrapy实例详解

生成项目

scrapy提供一个东西来生成项目,生成的项目中预置了一些文件,用户需要在这些文件中添加本身的代码。

打开呼吁行,执行:scrapy startproject tutorial,生成的项目雷同下面的布局

tutorial/

   scrapy.cfg

   tutorial/

       __init__.py

       items.py

       pipelines.py

       settings.py

       spiders/

           __init__.py

           …

scrapy.cfg是项目标设置文件

用户本身写的spider要放在spiders目次下面,一个spider雷同

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)

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

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.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

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工具中。

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

在呼吁行执行scrapy的时候,我们可以加两个参数,让scrapy把parse要领返回的items输出到json文件中

scrapy crawl dmoz -o items.json -t json

items.json会被放在项目标根目次

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

上面的示例中scrapy只抓取了start_urls内里的两个url的内容,可是凡是我们想实现的是scrapy自动发明一个网页上的所有链接,然后再去抓取这些链接的内容。为了实现这一点我们可以在parse要领内里提取我们需要的链接,然后结构一些Request工具,而且把他们返回,scrapy会自动的去抓取这些链接。代码雷同:

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

#p#分页标题#e#

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

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

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("//p/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

对比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生存到数据库。

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

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

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

添加一行

ITEM_PIPELINES = ['dirbot.pipelines.FilterWordsPipeline']

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

    关键字:

在线提交作业