Scrapy从入门到精通(1)

Scrapy简介

Scrapy是一个用Python语言(基于Twisted框架)编写的开源网络爬虫框架.

Scrapy安装

linux:

conda install scrapy

win:略
Mac:没钱用
测试

import scarpy
print(scrapy.version_info)
(1, 5, 0)

编写第一个Scrapy

创建项目的命令:
这里写图片描述
结构目录:
这里写图片描述
练习网站

http://books.toscrape.com/

分析网站
右键检查元素
这里写图片描述

next的url:
<li class="next"><a href="page-3.html">next</a></li>
是一个相对地址

实现spider

  • name属性
一个项目中可能有多个爬虫,每个爬虫的name属性是自身的唯一标示,
name不能重复 例子中name=‘books’
  • start_urls属性
一个爬虫开始的页面(可以为多个),起始爬取点'http://books.topcrape.com'
  • parse方法
页面下载完成后 Scrapy会回调一个页面解析函数(默认parse方法),完成
1.提取页面中的数据(XPath或css选择器)
2.提取页面中的链接,并产生对链接页面的下载请求
# -*- coding: utf-8 -*-
import scrapy


class BooksSpider(scrapy.Spider):
    name = 'books'
    # 定义爬虫起点
    start_urls = ['http://books.toscrape.com/']

    #    def start_requests(self):
    #       yield scrapy.Request('http://books.toscrape.com/',
    #                            callback=self.parse_book,
    #                            headers={'User-Agent': 'Mozilla/5.0'},
    #                            dont_filter=True)

    # # 改用parse_book作为回调函数
    # def parse_book(response):
    #
    #     pass

    # def parse(self, response):
    #     # 提取数据
    #     # <article class="product_pod">
    #     # 每一本书的信息在<article class="product_pod"中>
    #     # 用css()方法找到所有这样的article元素,并依次迭代
    #     for book in response.css('article.product_pod'):
    #         # 书名信息在aritcle>h3>a元素的title属性里
    #         # <a href="how-music-works_979/index.html" title="How Music Works">How Music Works</a>
    #         name = book.xpath('./h3/a/@title').extract_first()
    #
    #         # 书价在<p class="price_color">£37.32</p>的text中
    #         price = book.css('p.price_color::text').extract_first()
    #         yield {
    #             'name': name,
    #             'price': price,
    #         }
    #
    #     # 提取链接
    #     # 下一页的url在<li class="next"><a href="page-3.html">next</a></li>
    #     next_url = response.css('ul.pager li.next a::attr(href)').extract_first()
    #     if next_url:
    #         # 若找不到下一页,得到绝对路径,构造新的requset对象
    #         next_url = response.urljoin(next_url)
    #         # yield scrapy.Request(next_url, callback=self.parse)

    def parse(self, response):
        for book_url in response.css("article.product_pod > h3 > a ::attr(href)").extract():
            yield scrapy.Request(response.urljoin(book_url), callback=self.parse_book_page)
        # 然后是获取相应内容,并创建解析函数
        next_page = response.css("li.next > a ::attr(href)").extract_first()
        if next_page:
            yield scrapy.Request(response.urljoin(next_page), callback=self.parse)
            # 关键之处之一,找到下一个链接

    def parse_book_page(self, response):
        # 解析函数,我们在Scrapy中使用,Selector与xpath选择器,css选择器与一些其他Python代码实现该功能
        item = {}
        product = response.css("div.product_main")
        item["title"] = product.css("h1 ::text").extract_first()
        item['category'] = response.xpath(
            "//ul[@class='breadcrumb']/li[@class='active']/preceding-sibling::li[1]/a/text()"
        ).extract_first()
        item['description'] = response.xpath(
            "//div[@id='product_description']/following-sibling::p/text()"
        ).extract_first()
        item['price'] = response.css('p.price_color ::text').extract_first()
        yield item

Scrapy框架结构工作原理

  • ENGING 引擎,框架的核心,其他组件在其控制下工作 内部组件
  • SCHENDULER 调度器,负责对spider提交的下载请求进行调度 内部组件
  • DOWNLOAD 下载器 ,下载页面(request response) 内部组价
  • spider 提取页面中的数据 产生对新页面的下载请求 用户实现
  • MIDDLEWARE 中间件,负责对request response对象进行处理 可选组价
  • ITEM PIPELINE 数据管道 对爬去的数据进行处理

spider

  • request :Scrapy中http请求对象
  • response:Scrapy中响应
  • item:从页面中爬去一项数据

    request 和response好比血液 item好比代谢产物


request response

Request(url,[,callback,method='GET',headers,body,cookies,meta,encoding='utf-8',priority=0,priority = 0,dont_filter=False,errback])
  • url地址
  • callback 页面解析函数callback类型,request对象请求的页面下载完成后,该参数指定的页面解析函数被调用。默认Spider的parse方法
  • method Http请求方法,默认‘GET’
  • headers Http请求的头部字典,dict类型。若其中某些值为NONE,不发送该http头部{‘Cookie’:None}:禁止发送cookie
  • body Http请求的正文,bytes或str
  • cookie dict类型
  • meta request的元数据字典,dict类型,用于给框架中的其他组件传递信息。其他组件也可以用request对象的meta属性访问该元数据字典(request.meta),也用给相应处理函数传递信息
  • ecoding utf-8
  • priority 请求的优先级默认值为0 优先级高的先下载
  • dont_filter 默认dont_filter=false 避免重复下载一个url 。=true时,强制下载一个url
  • errback 请求异常或者404时的回调函数

response用来描述一个http响应,response是一个基类,如下子类

  • TextResponse
  • HtmlResponse
  • XmlResponse
    三者只有细微的差异,以HtmlResponse讲解
  • url str
  • status 相应状态码 200 404
  • header 头部 字典类型
response.header.get('Content-Type')
response.headers.getlist('Set-cookie')
  • body 正文文本 bytes
  • text str 由response.body使用response.ecoding解码得到
response.text = response.decode(response.encoding)
  • encoding
  • requset
  • meat 将要传递给响应处理函数的信息通过meta参数传递;再有response.meta取出
  • selector 在response中提取数据
  • xpath(query) 使用xpath在response中提取数据,实际是response.selector.xpath方法的快捷方式
  • css(query)使用css在response中提取数据, 是response.selector.css的快捷
  • urljoin(url) 构造绝对的url 例如response.url为http://www.example.com/a url为b/index.html调用response.urljoin(url)结果为:http://www.example.com/a/b/index.html

Spider开发流程

  • 从那些页面开始爬取
  • 对于一个已经下载的页面,获取其中那些数据
  • 爬取完当前页面后,接下来爬取那些页面

实现一个Spider需要完成一下四部

  • 继承scrapy.Spider
  • 为Spider取名
  • 设定起始爬取点
  • 实现页面解析函数

继承scrapy.Spider
scrapy框架提供一个Spider类,编写的Spider需要继承他

import scrapy
class BooksSpider(scrapy.Spider):

为Spider命名
name为唯一标示

class BooksSpider(scraoy.Spider)
name = "books"

设定爬取的起点
通过start_urls来设定起始爬取点

start_urls = ['http://books.toscrape.com']

Spider基类的start_requests方法帮助我们构造并提交了Request对象,
原理:

  • 起始下载请求是由Scrapy引擎调用Spider对象start_requests方法提交,引擎自动调用提交
  • 在start_requsests方法中,self.start.urls便是我们定义的起始点,对其进行迭代,用迭代的每个url作为参数调用make_requests_from_url方法
  • 在make_requests_from_url方法中,真正构造request对象代码使用url和dont_filter参数构造request对象
  • 构造request对象并没有传递callback参数来指定页面解析函数,因此会默认将parse方法作为页面解析函数
  • 起始爬去点可能有多个,start_requests方法需要返回一个可迭代对象,其中每一个元素是一个request对象

    由于下载请求是由start_request方法产生的。可以重写start_request方法,直接构造并提取爬去点的request对象。例如在:想为request添加特定的HTTP请求头部,或想为request指定特定的页面解析函数
#实现start_request方法定义起始爬取点的实例
class BooksSpider()
    def start_requests(self):
        yield scrapy.Request('http://books.toscrape.com/',
                             callback=self.parse_book,
                             headers={'User-Agent':'Mozilla/5.0'},
                             dont_filter=True)
    #改用parse_book作为回调函数
    def parse_book(response):

实现页面解析函数

页面解析函数也就是构造request对象时调用callback参数指定的回调函数(默认parse方法)。
它完成一下步骤

  • 使用选择器提取页面中的数据,将数据封装后(item或字典)提交给Scrapy引擎
  • 使用选择器或LinkExtractor提取页面中的链接,用其构造新的request对象并提交给Scrapy引擎(下载链接页面)

    一个页面范湖多个链接,因此页面解析函数必须返回一个迭代对象(通常被实现为一个生成器函数),每次迭代返回一项数据(item 字典)或者一个request对象

猜你喜欢

转载自blog.csdn.net/weixin_39381833/article/details/80875413