爬虫入门15Scrapy基本概念介绍—命令行参数和Spider

Posted 一步一步学Python

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬虫入门15Scrapy基本概念介绍—命令行参数和Spider相关的知识,希望对你有一定的参考价值。


创建一个scrapy项目

首先我们要做的就是创建一个项目,基本的命令如下:

scrapy startproject myproject [project_dir]

如果指定了project_dir,那么就会在该目录下创建一个project。
如果没有指定project_dir时,会在当前命令行目录下创建项目。
然后我们就可以在项目根目录下进行一系列操作了。
推荐创建scrapy项目后,使用pycharm来管理,写代码或者命令行操作都要简单很多。

可用的命令工具

可以通过scrapy-h来获取每个命令的具体信息。
也可以使用scrapy -h来获取所有的可用命令。

全局命令:

startproject
genspider
settings
runspider
shell
fetch
view
version

Porject-only命令

crawl
check
list
edit
parse
bench

每个命令的用法

startproject

上面讲过了,用于创建一个项目。

genspider

基本命令格式如下:

scrapy genspider [-t template] <name> <domain>

在当前目录下创建一个spider文件;
或者在当前项目的spider文件夹中,如果是在项目命令行中使用的话。

参数,设置为spider的文件名, 参数用于生成allowed_domains和start_urls属性。
简单举个例子:

$ scrapy genspider -l
Available templates:
  basic
  crawl
  csvfeed
  xmlfeed

$ scrapy genspider example example.com
Created spider 'example' using template 'basic'

$ scrapy genspider -t crawl scrapyorg scrapy.org Created spider 'scrapyorg' using template 'crawl'

我更倾向于自己创建spider文件,而不是使用命令行。

crawl

基本命令格式:

scrapy crawl <spider>

用于启动爬取,指定spider。

$ scrapy crawl myspider
[ ... myspider starts crawling ... ]

check

scrapy check [-1] <spider>

运行契约检查。

$ scrapy check -l
first_spider
  * parse
  * parse_item
second_spider
  * parse
  * parse_item

list

用于列举出所有可用的spider。
这里的spider指的是我们定义的爬虫,如果设置了name属性,那就会显示name来。

fetch

scrapy fetch [OPTION] <url>

通过Scrapy下载指定的url,然后私用标准输出格式写出来。
举个例子先:

$ scrapy fetch --nolog http://www.example.com/some/page.html
[ ... html content here ... ]

$ scrapy fetch --nolog --headers http://www.example.com/
{'Accept-Ranges': ['bytes'], 'Age': ['1263   '], 'Connection': ['close     '], 'Content-Length': ['596'], 'Content-Type': ['text/html; charset=UTF-8'], 'Date': ['Wed, 18 Aug 2010 23:59:46 GMT'], 'Etag': ['"573c1-254-48c9c87349680"'], 'Last-Modified': ['Fri, 30 Jul 2010 15:30:18 GMT'], 'Server': ['Apache/2.2.3 (CentOS)']}

Spiders

我们讲一个spider,其实就是一个类,这个类描述了如何爬取一个页面,包括如何运行爬取命令,如何解析页面的数据。
创建一个spider就是创建一个继承scrapy.Spider的类,在这个类中定义一些属性和函数。
下面我们来讲一下这个类的成员。

scrapy.Spider

每个spider都要继承这个类。
该类没有提供特殊的功能。只是提供了一个默认的start_requests()实现,从start_urls属性发送请求,然后调用spider的parse方法,来处理每个response。

name

用于定义spider的名称,调用时直接使用name属性即可。

allowed_domains

start_urls

爬取的目标网址组成的list。

crawler

这个属性通过from_crawler()类方法来设置,与Crawler对象链接。

from_crawler(crawler, args, *kwargs)

Scrapy使用这个方法来创建spider。
无需直接重写这个方法,其优先级要高于init()方法。

start_requests()

这个方法返回一个迭代器,第一次使用这个spider来爬取的请求。
Scrapy只会调用一次该方法,所以将该方法实现为一个生成器是很安全的。
默认的实现,生成Request(url,dont_filter=True),针对start_urls中的每个url。
如果想要改变用于开始爬取域名的请求,我们可以重写这个方法。
举个例子,如果我们想通过POST请求登陆一个页面,可以这么写:

class MySpider(scrapy.Spider):
    name = 'myspider'

    def start_requests(self):
        return [scrapy.FormRequest("http://www.example.com/login",
                                   formdata={'user': 'john', 'pass': 'secret'},
                                   callback=self.logged_in)]
   def logged_in(self, response):        # here you would extract links to follow and return Requests for        # each of them, with another callback        pass

parse(response)

这个方法是默认的调用方法,用于分析下载的response。
parse方法负责分析response,返回爬取的数据和更多要follow的URL。

上面解读了一些spider类中常用的方法,我们再来看一个例子:

import scrapyclass MySpider(scrapy.Spider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = [        'http://www.example.com/1.html',        'http://www.example.com/2.html',        'http://www.example.com/3.html',
    ]
   def parse(self, response):        self.logger.info('A response from %s just arrived!', response.url)

从一个单一请求,返回多重Requests和item。
举个例子:

import scrapyclass MySpider(scrapy.Spider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = [        'http://www.example.com/1.html',        'http://www.example.com/2.html',        'http://www.example.com/3.html',
    ]
   def parse(self, response):        for h3 in response.xpath('//h3').extract():            yield {"title": h3}        for url in response.xpath('//a/@href').extract():            yield scrapy.Request(url, callback=self.parse)

如果不使用start_urls,我们可以使用start_requests(),我们可以使用Items,设置data有更多的结构。

import scrapyfrom myproject.items import MyItem
class
MySpider(scrapy.Spider):
   name = 'example.com'    allowed_domains = ['example.com']
   def start_requests(self):        yield scrapy.Request('http://www.example.com/1.html', self.parse)
       yield scrapy.Request('http://www.example.com/2.html', self.            
       yield
scrapy.Request('http://www.example.com/3.html', self.                    
   def parse(self, response):        for h3 in response.xpath('//h3').extract():
           yield MyItem(title=h3)        
       for url in response.xpath('//a/@href').extract():      
           yield scrapy.Request(url, callback=self.parse)

Spider参数

spider能够接受参数,用来修改spider的行为。一些常见的用法是用来定义起点的url,或者限定爬取网页的特定部分。
spider参数都使用-a选项来传递crawl命令,举个例子:

scrapy crawl myspider -a category=electronics

spider能够在init方法中获取参数。举例:

import scrapyclass MySpider(scrapy.Spider):
    name = 'myspider'

    def __init__(self, category=None, *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs)
        self.start_urls = ['http://www.example.com/categories/%s' % category]        # ...

init方法会将任何一个参数赋值为spider的属性。上面的例子可以写成如下这种:

import scrapyclass MySpider(scrapy.Spider):
    name = 'myspider'

    def start_requests(self):
        yield scrapy.Request('http://www.example.com/categories/%s' % self.category)

请务必牢记spider的参数一定是字符串。
如果想要从命令行设置start_urls属性,那就要自行将其转换成一个list,可可以使用json.loads,然后设置其为属性。

Generic Spiders

Scrapy提供了一些有用的普通spider,让我们来扩展。目的是提供一些便利的功能,基于特定的规则。
假设我们已经声明了一个TestItem类,在myproject.items模块中定义:

import scrapyclass TestItem(scrapy.Item):
    id = scrapy.Field()
    name = scrapy.Field()
    description = scrapy.Field()

CrawlSpider

这是经常用来爬取常规页面的spider,它提供了一个方便的机制,设置了一系列规则。
也许它不是最合适的spider,但是适用普通的案例。我们可以从这个spider开始,然后重写它,或者直接实现你需要的功能。

import scrapyfrom scrapy.spiders import CrawlSpider, Rulefrom scrapy.linkextractors import LinkExtractorclass MySpider(CrawlSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com']

    rules = (        # Extract links matching 'category.php' (but not matching 'subsection.php')
        # and follow links from them (since no callback means follow=True by default).
        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),        # Extract links matching 'item.php' and parse them with the spider's method parse_item
        Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
    )
   def parse_item(self, response):        self.logger.info('Hi, this is an item page! %s', response.url)        item = scrapy.Item()        item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')        item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()        item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()        return item

以上是关于爬虫入门15Scrapy基本概念介绍—命令行参数和Spider的主要内容,如果未能解决你的问题,请参考以下文章

Python爬虫从入门到放弃(十三)之 Scrapy框架的命令行详解

Python网络爬虫实战-Scrapy视频教程 Python系统化项目实战课程 Scrapy技术课程

Python爬虫从入门到成妖之3-----Scrapy框架的命令行详解

Python 爬虫-Scrapy框架基本使用

python scrapy爬虫框架概念介绍(个人理解总结为一张图)

python爬虫scrapy入门6:Scrapy中runspider和crawl的区别