爬虫

4 篇文章 0 订阅
3 篇文章 0 订阅
本文介绍了Scrapy爬虫的流程,包括下载页面、提取数据和链接、URL去重。详细讲述了Scrapy的安装、创建项目、编写爬虫以及运行。通过实例展示了如何爬取书籍信息,提取书名和价格。最后,讨论了Scrapy框架结构和工作原理,包括Request和Response对象,以及页面解析和数据封装。
摘要由CSDN通过智能技术生成


爬虫程序的流程

下载页面-->提取页面中的数据-->提取页面中的链接-->URL去重

Scrapy简介及安装

在任意操作系统下,可以使用pip安装Scrapy,例如:
$pip install scrapy
为确认Scrapy已安装成功,首先在Python中测试能否导入Scrapy模块:
    >>>    import    scrapy                    
    >>>    scrapy.version_info    
        (1,    3,    3)
通过了以上两项检测,说明Scrapy安装成功了。Scrapy安装过程中可能会遇到一些问题,可能还要
安装win32api、lxml等,应根据报错内容百度相应的方法可以解决,也有可能环境缺少安装包,安装即可

编写Scrapy爬虫

爬取http://books.toscrape.com网站中取书籍信息,这样的书籍列表页面一共有50页,每页有20本书,第一个例子应尽量简单。我们下面以这个项目仅爬取所有图书(1000本)的书名和价格信息。

1.创建项目:在命令行输入scrapy startproject example
使用tree查看目录结构:tree    
2.分析页面,一般用xpath或者css得到元素
3.实现Spider
实现爬虫的Python文件应位于exmaple/spiders目录下,在该目录下创建 新文件book_spider.py。然后,在book_spider.py中实现爬虫BooksSpider,
代码如下:
import    scrapy
class    BooksSpider(scrapy.Spider):
    name = "books"
    start_urls = ['http://books.toscrape.com/']
    def parse(self, response):
        for book in response.css('article.product_pod'):
            name = book.xpath('./h3/a/@title').extract_first()
            price = book.css('p.price_color::text').extract_first()
            yield  {'name':name,
                    'price': price,
                    }
            next_url = response.css('ul.pager    li.next    a::attr(href)').extract_first()
            print(next_url)
            if next_url:
                next_url = response.urljoin(next_url)
                yield scrapy.Request(next_url, callback=self.parse)

上述代码注解:
name属性
    一个Scrapy项目中可能有多个爬虫,每个爬虫的name属 性是其自身的唯一标识,在一个项目中不能有同名的爬虫,本例中的爬虫取名为'books',这个是在运行时需要用到。
  start_urls属性
  一个爬虫总要从某个(或某些)页面开始爬取,我们称 这样的页面为起始爬取点,start_urls属性用来设置一个 爬虫的起始爬取点。在本例中只有一个起始爬取 点'http://books.toscrape.com'。
  parse方法
    当一个页面下载完成后,Scrapy引擎会回调一个我们指定的页面解析函数(默认为parse方法)解析页面。一个页面解析函数通常需要完成以下两个任务:
    提取页面中的数据(使用XPath或CSS选择器)。
    提取页面中的链接,并产生对链接页面的下载请 求。

4.运行爬虫,scrapy crawl books -o    books.csv
  可能会错写报错,需要在setting文件中设置ROBOTSTXT_OBEY = False,设置robot协议不遵守


Scrapy框架结构及工作原理

上几种对象在框架中的流动过程。

● 当SPIDER要爬取某URL地址的页面时,需使用该URL构造一 个Request对象,提交给ENGINE(图2-1中的1)。

● Request对象随后进入SCHEDULER按某种算法进行排队,之 后的某个时刻SCHEDULER将其出队,送往DOWNLOADER(图 2-1中的2、3、4)。

● DOWNLOADER根据Request对象中的URL地址发送一次HTTP 请求到网站服务器,之后用服务器返回的HTTP响应构造出一个 Response对象,其中包含页面的HTML文本(图2-1中的5)。

● Response对象最终会被递送给SPIDER的页面解析函数(构造 Request对象时指定)进行处理,页面解析函数从页面中提取数 据,封装成Item后提交给ENGINE,Item之后被送往ITEM PIPELINES进行处理,最终可能由EXPORTER(图2-1中没有显 示)以某种数据格式写入文件(csv,json);另一方面,页面解 析函数还从页面中提取链接(URL),构造出新的Request对象提 交给ENGINE(图2-1中的6、7、8)。

 

Request对象
构造函数:Request(url[,callback,    method='GET',headers,body,cookies,meta,                                    encoding='utf8',priority=0,    dont_filter=False,errback])
下面依次介绍这些参数。
●url(必选)
  请求页面的url地址,bytes或str类型, 如'http://www.python.org/doc'。
●callback
  页面解析函数,    Callable类型,Request对象请求的页面  下载完成后,由该参数指定的页面解析函数被调用。如 果未传递该参数,默认调用Spider的parse方法。
●method
  HTTP请求的方法,默认为'GET'。
●headers
  HTTP请求的头部字典,dict类型,例如{'Accept': 'text/html',    'User-Agent':Mozilla/5.0'}。如果其中某项的值 为None,就表示不发送该项HTTP头部,例如{'Cookie': None},禁止发送Cookie。
●body
  HTTP请求的正文,bytes或str类型。
●cookies
  Cookie信息字典,dict类型,例如{'currency':    'USD', 'country':    'UY'}。
●meta
  Request的元数据字典,dict类型,用于给框架中其他组 件传递信息,比如中间件Item    Pipeline。其他组件可以使 用Request对象的meta属性访问该元数据字典 (request.meta),也用于给响应处理函数传递信息,详 见Response的meta属性。
●encoding
  url和body参数的编码默认为'utf-8'。如果传入的url或 body参数是str类型,就使用该参数进行编码
●priority
  请求的优先级默认值为0,优先级高的请求优先下载
●dont_filter
  默认情况下(dont_filter=False),对同一个url地址多次 提交下载请求,后面的请求会被去重过滤器过滤(避免 重复下载)。如果将该参数置为True,可以使请求避免 被过滤,强制下载。例如,在多次爬取一个内容随时间 而变化的页面时(每次使用相同的url),可以将该参数 置为True。
●errback
  请求出现异常或者出现HTTP错误时(如404页面不存 在)的回调函数


在实际应用中,我们几乎只调用Request的构造器创建对象,但也可以 根据需求访问Request对象的属性,常用的有以下几个:
    ●url
    ●method
    ●headers
    ●body
    ●meta

Response对象
Response对象用来描述一个HTTP响应,Response只是一个基类,根据 响应内容的不同有如下子类: ● TextResponse
● HtmlResponse
● XmlResponse
当一个页面下载完成时,下载器依据HTTP响应头部中的Content-Type 信息创建某个Response的子类对象。我们通常爬取的网页,其内容是 HTML文本,创建的便是HtmlResponse对象,其中HtmlResponse和 XmlResponse是TextResponse的子类。实际上,这3个子类只有细微的差 别,这里以HtmlResponse为例进行讲解。
下面介绍HtmlResponse对象的属性及方法。
● url
HTTP响应的url地址,str类型。
● status
HTTP响应的状态码,int类型,例如200,404。 ● headers HTTP响应的头头部,类字典类型,可以调用get或getlist 方法对其进行访问,例如:
                    response.headers.get('Content-Type')                    response.headers.getlist('Set-Cookie')
● body
HTTP响应正文,bytes类型。
● text
文本形式的HTTP响应正文,str类型,它是由 response.body使用response.encoding解码得到的,即
                    reponse.text    =    response.body.decode(response.encoding)
● encoding HTTP响应正文的编码,它的值可能是从HTTP响应头部 或正文中解析出来的。
● request 产生该HTTP响应的Request对象。
● meta 即response.request.meta,在构造Request对象时,可将要 传递给响应处理函数的信息通过meta参数传入;响应处 理函数处理响应时,通过response.meta将信息取出。
● selector Selector对象用于在Response中提取数据(选择器相关话 题在后面章节详细讲解)。 ● xpath(query) 使用XPath选择器在Response中提取数据,实际上它是 response.selector.xpath方法的快捷方式(选择器相关话题 在后面章节详细讲解)。
● css(query) 使用CSS选择器在Response中提取数据,实际上它是 response.selector.css方法的快捷方式(选择器相关话题在 后面章节详细讲解)。
● urljoin(url) 用于构造绝对url。当传入的url参数是一个相对地址时, 根据response.url计算出相应的绝对url。例如, response.url为http://www.example.com/a,url为 b/index.html,调用response.urljoin(url)的结果为 http://www.example.com/a/b/index.html

实际上,对于起始爬取点的下载请求是由Scrapy引擎调用 Spider对象的start_requests方法提交的,由于BooksSpider类没有实 现start_requests方法,因此引擎会调用Spider基类的start_requests 方法。 ● 在start_requests方法中,self.start_urls便是我们定义的起始爬 取点列表(通过实例访问类属性),对其进行迭代,用迭代出的 每个url作为参数调用make_requests_from_url方法。 ● 在make_requests_from_url方法中,我们找到了真正构造 Reqeust对象的代码,仅使用url和dont_filter参数构造Request对 象。 ● 由于构造Request对象时并没有传递callback参数来指定页面解 析函数,因此默认将parse方法作为页面解析函数。此时 BooksSpider必须实现parse方法,否则就会调用Spider基类的parse 方法,从而抛出NotImplementedError异常(可以看作基类定义了 一个抽象接口)。 ● 起始爬取点可能有多个,start_requests方法需要返回一个可迭 代对象(列表、生成器等),其中每一个元素是一个Request对 象。这里,start_requests方法被实现成一个生成器函数(生成器对 象是可迭代的),每次由yield语句返回一个Request对象。 由于起始爬取点的下载请求是由引擎调用Spider对象的start_requests方
法产生的,因此我们也可以在BooksSpider中实现start_requests方法(覆盖 基类Spider的start_requests方法),直接构造并提交起始爬取点的Request对 象。在某些场景下使用这种方式更加灵活,例如有时想为Request添加特定 的HTTP请求头部,或想为Request指定特定的页面解析函数。

到此,我们介绍完了为爬虫设定起始爬取点的两种方式:
 ● 定义start_urls属性。 ● 实现start_requests方法

实现页面解析函数
页面解析函数也就是构造Request对象时通过callback参数指定的回调 函数(或默认的parse方法)。页面解析函数是实现Spider中最核心的部 分,它需要完成以下两项工作: ● 使用选择器提取页面中的数据,将数据封装后(Item或字典) 提交给Scrapy引擎。 ● 使用选择器或LinkExtractor提取页面中的链接,用其构造新的 Request对象并提交给Scrapy引擎(下载链接页面

使用Selector提取数据
Selector类的实现位于scrapy.selector模块,创建Selector对象时,可将 页面的HTML文档字符串传递给Selector构造器方法的text参数:
from scrapy.selector import    Selector
selector=Selector(text=text)
也可以使用一个Response对象构造Selector对象,将其传递给Selector构 造器方法的response参数:
    from scrapy.selector import    Selector
    from scrapy.http import    HtmlResponse
    response=HtmlResponse(url='http://www.example.com',    body=body)                    selector=Selector(response=response)

选中数据
    selector_list=selector.xpath('//h1')
 提取数据
调用Selector或SelectorLis对象的以下方法可将选中的内容提取:
● extract()
● re()
● extract_first()    (SelectorList专有)
● re_first()    (SelectorList专有

XPath
XPath语法
/         选中文档根
.         选中当前节点
..        选中当前节点的父节点
ELEMNT    选中节点中所有ELEMNT元素节点
//ELEMNT  选中后代节点中所有的ELEMENT节点
*         选中所有元素
text()    选中所有文本子节点
@ATTR     选中名为ATTR的属性节点
@*        选中所有节点
[谓语]    谓语用来查找某个节点或者包含某个特定值的节点

常用函数
string(arg)
possition()
last()
contains(str2,str2)

css选择器
了CSS选择器的一些基本语法
*                  选中所有元素
E                  选中E元素
E1,E2              选中E1和E2元素
E1 E2              选中E1后代元素中的E2
E1>E2              选中E1中的元素E2
.class             选中class属性包含class的元素
#ID                选中id属性为ID的元素
[ATTR]              选中包含ATTR属性的元素
[ATTR=VALUE]        选中包含ATTR属性且属性值为VALUE的元素
[ATTR~=VALUE]       选中包含ATTR属性且包含VALUE的元素
E:nth-child(n)      选中E元素,且改元素必须是其父元素的第n个子元素
E:nth-last-child(n) 选中E元素,且改元素必须是其父元素的倒数第n个子元素
E:frist-child       选中E元素,且改元素必须是其父元素的第一个元素
E:last-child        选中E元素,且改元素必须是其父元素的倒数第一个元素
E:empty             选中没有子元素的E元素
E::text             选中E元素的文本节点

使用Item封装数据

Scrapy提供了以下两个类,用户可以使用它们自定义数据类(如书籍 信息),封装爬取到的数据: Item基类 自定义数据类(如BookItem)的基类。
● Field类 用来描述自定义数据类包含哪些字段(如name、price 等)。 自定义一个数据类,只需继承Item,并创建一系列Field对象的类属性 (类似于在Django中自定义Model)即可。以定义书籍信息BookItem为 例,它包含两个字段,分别为书的名字name和书的价格price,代码如下:
from scrapy    import Item,Field
class BookItem(Item):
      name=Field()
      price=Field()

使用Item    Pipeline处理数据
以下是Item    Pipeline的几种典型应用:
● 清洗数据。
● 验证数据的有效性。
● 过滤掉重复的数据。
● 将数据存入数据库。
在创建一个Scrapy项目时,会自动生成一个pipelines.py文件,它用来 放置用户自定义的Item    Pipeline,在example项目的pipelines.py中实现 PriceConverterPipeline,代码如下:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值