Scrapy

Scrapy之路(一)

前面安装什么的我就不说了,一大堆坑,坑了我两天才终于把Scrapy安装好,踩的坑网上都有怎么填我就不详细说了。开始正文学习。

全局命令

startprojiect

语法:scrapy startproject <projectname>
在当前目录下创建一个自己命名的scrapy项目

settings

语法:scrapy setting [options]
运行一些设定

runspider

语法:scrapy runspider <spiderfile.py>
在未创建项目的情况下,运行一个编写在python文件中的spider

shell

语法:scrapy shell [url]
启动Scrpy shell,如果给定url就运行指定的url,如果没有就只启动交互式命令行

fetch

语法:scrapy fetch <url>
使用Scrapy下载器下载给定的url,并且将获取的内容输出。也就是打印url 的html代码。

view

语法:scrapy view <url>
在你的默认浏览器中打开给定的URL,并以Scrapy spider获取到的形式展现。 有些时候spider获取到的页面和普通用户看到的并不相同,一些动态加载的内容是看不到的, 因此该命令可以用来检查spider所获取到的页面。

version

语法:scrapy version [-v]
输出scrapy的版本

项目命令

crawl

语法::scrapy crawl <spider_name>
使用你项目中的spider进行爬取,即启动你的项目。这个命令将会经常用到,我们会在后面的内容中经常使用。

check

语法::crapy check [-l] <spider>
运行contract检查,检查你项目中的错误之处。

list

语法:scrapy list
列出当前项目中所有可用的spider。每行输出一个spider。

genspider

语法:scrapy genspider [-t template] <name> <domain>
在当前项目中创建spider。该方法可以使用提前定义好的模板来生成spider。您也可以自己创建spider的源码文件。

Spiders

Spider类定义了如何爬取某个网站。包括了爬取的动作(比如是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。也就是说,Spider是定义爬取的动作和分析某个网页的地方。
大致工作流程是这样的:

  • 以初始的URL初始化Request,并设置回调函数,当该request下载完毕并返回时,将生成response,并作为参数传给回调函数,spider中初始的request是通过start_requests()来获取。start_requests()获取start_urls中的url,并以parse以回调函数生成request
  • 在回调函数内分析返回的网页内容,可以返回item对象,或者dict或者request,以及是一个包含三者的可迭代的容器,返回的request对象之后会经过scrapy处理,下载相应的内容,并调用设置的callback函数
  • 在回调函数内,可以通过lxml,bs4,xpath,css等方法获取想要的内容生成item
  • 最后将Item传递给pipeline处理

在运行crawl的时候可以添加-a传递spider参数。
scrapy crawl myspider -a category=electronics

spider在构造器(constructor)中获取参数:

import scrapy

class MySpider(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]

name

定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。 不过您可以生成多个相同的spider实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的。

如果该spider爬取单个网站(single domain),一个常见的做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite 。

allowed_domains

可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进。

start_urls

URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。 因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。

start_requests()

该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取的第一个Request。
当spider启动爬取并且未制定URL时,该方法被调用。 当指定了URL时,make_requests_from_url() 将被调用来创建Request对象。 该方法仅仅会被Scrapy调用一次,因此您可以将其实现为生成器。
该方法的默认实现是使用 start_urls 的url生成Request。

parse(response)

当response没有指定回调函数时,该方法是Scrapy处理下载的response的默认方法。
parse 负责处理response并返回处理的数据以及(/或)跟进的URL。 Spider 对其他的Request的回调函数也有相同的要求。
该方法及其他的Request回调函数必须返回一个包含 Request 及(或) Item 的可迭代的对象。
参数: response (Response) – 用于分析的response

closed(reason)

当spider关闭时,该函数被调用。

Selector 选择器

Scrapy提取数据有自己的一套机制,被称作选择器(selectors),通过特定的Xpath或者CSS表达式来选择HTML文件的某个部分
Xpath是专门在XML文件中选择节点的语言,也可以用在HTML上。

XPath选择器

  • nodeName:选取此节点的所有节点
  • /:从根节点选取
  • //:从匹配选择的当前节点选择文档中的节点,不考虑它 们的位置
  • .:选择当前节点
  • .. :选取当前节点的父节点
  • @:选取属性
  • * :匹配任何元素节点
  • @*:匹配任何属性节点
  • Node():匹配任何类型的节点

CSS选择器

CSS层叠样式表,语法由两个主要部分组成:选择器,一条或多条声明
Selector {declaration1;declaration2;……}

下面为常用的使用方法:

declaration1 declaration2 说明
.class .color 选择class=”color”的所有元素
* * 选择所有元素
element p 选择所有P元素
element,element div,p 选择所有div元素和所有p元素
element,element div p 选择div标签内部的所有p元素
[attribute] [target] 选择带有targe属性的所有元素
[arrtibute=value] [target=_blank] 选择target=”_blank”的所有元素
id info 选择id=”info”的所有元素

scrapy之数据项Item

简单来说,就是从非结构化的数据源(web页面)提取出结构化的数据。为了定义常见的输出数据格式,Scrapy提供了Item类。Item对象是一种简单的容器,用来搜集爬取到的数据。它提供了一个类似于字典的API,具有方便的语法来声明它们的可用字段。

各种Scrapy组件使用Item提供的额外信息:导出器查看已声明的字段,来找出列进行导出;通过Item字段的元数据使序列化可定制;trackref跟踪Item实例来帮助查)内存泄漏;等等

声明数据项

import scrapy
class A(scrapy.Item):
    name = scrapy.Filed()
    price = scrapy.Filed()
    stock = scrapy.Filed()
    last_updated = scrapy.Field(serializer=str)

Field对象被用来指定每个字段的元数据。比如,上面的示例中演示了last_updated字段的序列化函数。

你可以为每个字段指定任何种类的元数据。Field对象接受的值是没有限制的。出于同样的原因,所有可用的元数据关键字没有引用列表。每一个在Field对象中定义的关键字,都可能会被不同的组件使用,并且仅仅只有这些组件知道这些关键字。你也可以根据你的需求,在你的项目中使用其他Field关键字。Field对象的主要目的在于,提供一种方式在某个地方来定义所有的字段元数据。通常而言,那些行为依赖于每个字段的组件使用某些字段关键字来配置该行为。你必须参考它们的文档,以查看每个组件使用哪些元数据关键字。

需要注意的是,用于声明Item的Field对象不会被指定为类属性。相反,可以通过Item.fields属性来访问它们。
比如用上面代码中声明的A:

a = A(name="Gsuhy",price=100)
print(a)
-----------
{'name': 'Gsuhy', 'price': 100}

如果要获取字段的值,就用字典的方法访问就好了。

数据项加载器

数据项提供了一个容器,用于存储爬取到的数据。而数据项加载器提供了填充该容器的机制。
为了使用一个数据项加载器,首先你必须初始化它。你既可以使用类似于字典的对象(比如Item或者字典)来初始化它,也可以不使用它——在这种情况下,使用ItemLoader.default_item_class属性中指定的Item类,在数据项加载器构造函数中自动实例化一个Item。

然后,你可以在数据项加载器中收集值了,典型方式就是使用选择器Selector。你可以对同样的Item字段中添加不止一个值;数据项加载器自己会知道如何在以后使用适当的处理函数“连接”这些值。

from scrapy.laoder import ItemLoader
from myproject.items import Product


def parse(self, response):
    l = ItemLoader(item=Product(), response=response)
    l.add_xpath('name', '//div[@class="product_name"]')
    l.add_xpath('name', '//div[@class="product_title"]')
    l.add_xpath('price', '//p[@id="price"]')
    l.add_css('stock', 'p#stock]')
    l.add_value('last_updated', 'today')  # 你也可以使用文字值
    return l.load_item()

可以看到 ,name字段可以从2个不同的Xpath位置得到
换句话说,通过使用add_xpath()函数从两个XPath位置提取数据以便收集数据。随后,这个数据将分配给name字段。

然后,对price和stock字段使用类似的调用(后者使用带有add_css()函数的CSS选择器),最后使用不同的函数add_value()直接用字面值(today)填充last_updated字段。

最后,在收集所有数据时,将调用ItemLoader.load_item()函数,该函数实际返回先前调用add_xpath()add_css()add_value()函数提取和收集的数据来填充数据项。


   转载规则


《Scrapy》 Gsuhy 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录