爬虫学习笔记4---------scrapy框架

Scrapy框架

 

Scrapy

不是一个简单的函数功能库;而是一个专业的网络爬虫框架

Scrapy 足以支持一般商业服务所需的爬虫能力:持续爬取、商业服务、高可靠性

 

scrapy库的安装:

pip install scrapy

scrapy -h

Available commands:

  bench         Run quick benchmark test

  commands

  fetch         Fetch a URL using the Scrapy downloader

  genspider     Generate new spider using pre-defined templates

  runspider     Run a self-contained spider (without creating a project)

  settings      Get settings values

  shell         Interactive scraping console

  startproject  Create new project

  version       Print Scrapy version

  view          Open URL in browser, as seen by Scrapy

 

  [ more ]      More commands available when run from project directory

 

Unit1、Scrapy爬虫框架

 

一、Scrapy爬虫框架结构

 

  • 爬虫框架
    • 爬虫框架是实现爬虫功能的一个软件结构和功能组件集合。
    • 是一个半成品,帮助实现专业网络爬虫。
  • “5+2”结构:                                  已有实现,不用编写   
      • ENGINE            引擎
        • 控制所有模块之间的数据流
        • 根据条件触发事件
      • SCHEDULER    调度器
        • 对所有爬取请求进行调度管理,排访问顺序
      • ITEM PIPELINES (出口) 用户编写(也叫配置),对提取的信息进行后处理
        • 以流水线来处理Spider产生的爬取项
        • 有一组操作顺序组成,类似流水线,每个操作是一个Item Pipeline类型
        • 可能操作包括:清理、检验、查重爬取项的HTML数据、将数据储存到数据库
      • SPIDERS            (入口)  用户编写(也叫配置),提供初始URL链接,并解析所得网页内容,再提供链接
        • 解析Downloader返回的响应(Response)
        • 产生爬取项(scraped item)
        • 产生额外的爬取请求(Request)
      • DOWNLOADER    下载页面
      • Downloader Middlewares    (中间件)
        • 目的:实施Engine、Scheduler、Downloader之间进行用户可配置的控制
        • 功能:修改、丢弃、新增请求或响应(拦截)
      • Spider Middleware      (中间件)
        • 目的:对请求和爬取项再处理
        • 功能:修改、丢弃、新增请求或爬取项(拦截)

 

 

 

 

二、Requests  vs. Scrapy

 

  • 相同点:
    • 都可进行页面请求和爬取,是Python爬虫的两个重要技术路线。
    • 两都好用,文档丰富,入门简单。
    • 都么有处理js、提交表单、应对验证码等功能(可扩展)
  • 不同:

 

requests

Scrapy

页面级 网站级
功能库框架
并发性不足,性能差并发性好,性能较强(基于异步结构设计,有时太快会被反爬虫发现)
重点在于页面下载 重点在于爬虫框架
定制灵活一般定制灵活,深度定制困难
上手十分简单人门稍微难

 

三、Scrapy爬虫的常用命令

 

Scrapy命令行   (建立爬虫,运行爬虫)

Scrapy 是为持续运行设计的专业爬虫框架,提供操作的Scrapy命令行。

>scrapy <command> [options] [args]

 

命令行输入:

scrapy -h

 

常用命令:

startproject创建一个新工程scrapy startproject <name> [dir]
genspider创建一个爬虫scrapy genspider [options] <name> <domain>
settings获得爬虫配置信息scrapy settings [options]
crawl运行一个爬虫scrapy crawl <spider>
list列出工程中所有爬虫scrapy list
shell启动URL调试命令行scrapy shell [url]

 

Scrapy为什么采用命令行?

  • 命令行(而不是图形界面)更容易自动化,适合脚本控制。
  • 本质上,Scrapy是给程序员使用的,功能(而不是界面)更重要。

 

 


 

Unit2、Scrapy爬虫基本使用

 

产生步骤:

  1. 建立一个Scrapy爬虫工程
    • 命令行:D:\pycode>scrapy startproject python123demo
      • 生成工程目录:
        • Python123demo/------>外层目录
          • scrapy.cfg  ------>部署Scrapy爬虫的配置文件,服务器
          • Python123demo/-->Scrapy框架的用户自定义python代码
            • __init__.py-->初始化脚本
            • items.py  -->Items代码模板(继承类)
            • middlewares.py  -->Middlewares代码模板(继承类)
            • pipelines.py  -->Pipelines代码模板(继承类)
            • settings.py --->Scrapy爬虫的配置文件
            • spiders/   ----->Spiders代码模板目录(继承类)
              • __init__.py  ----->初始文件,无需修改
              • __pycache__/--->缓存目录,无需修改
  2. 在工程中产生一个Scrapy爬虫,产生一个Spider模板
    • 命令行:D:\pycode>cd python123demo
      •    D:\pycode\python123demo>scrapy genspider demo python123.io #爬取域名
      •    Created spider 'demo' using template 'basic' in module:  python123demo.spiders.demo作用:生成demo.py
  3. 编写产生的Spider模板
    • 修改dome.py文件
  4. 运行爬虫,获取网页

 

start_urls = ['http://python123.io/ws/demo.html']

 

#等价方法,完整代码部分 :

def start_requests(self):

    urls = [

            'http://python123.io/ws/demo.html'

           ]

    for url in urls:

        yield scrapy.Request(url=url, callback=self.parse)#当Url数量很大时,可以很有效的节省资源

 

yield关键字

                    yield <-->生成器

  • 生成器:一个不断产生值的函数
  • 包含yield语句的函数是一个生成器
  • 生成器每次产生一个值(yield语句),函数被冻结,被唤醒后再产生一个值。

 

#生成器写法

def gen(n):

     for i in range(n):

          yield i**2

for i in gen(5):

    print(i,' ', end="")

 

#普通写法

def square(n):

     ls = [i**2 for i in range(n)]

     return ls

for i in square(5):

    print(i,' ', end="")

 

##当n=1M、10M、100M或更大?生成器的重要优势

 

为何要使用生成器?

  • 生成器相比一次列出所有内容的优势
    • 更节省储存空间
    • 响应更迅速
    • 使用更加灵活

 

Scrapy爬虫的使用步骤:

  1. 创建一个工程和Spider模板
  2. 编写Spider
  3. 编写Item Pipeline
  4. 优化配置策略

 

Scrapy爬虫的数据类型:

1、Request类 (class scrapy.http.Request())

  •      Request对象表示一个HTTP请求
  •      由Spider生成,Downloader执行

 

属性、方法.url.method.headers.body.meta.copy()
说明对应URL对应请求方法.'GET''POST'

字典类型请求 头

头部自定义

字符串类型请求内容用户添加的扩展信息,Scrapy内部传递信息复制该请求

 

2、Response类 (class scrapy.http.Request())

  •  Request对象表示一个HTTP响应
  •  由Downloader生成,Spider执行

属性和方法:

.url.status.headers.body.flags.request.copy(0
对应URLHTTP状态码,默认200头部内容一组标记对应Request对象复制该响应

 

 

3、Item类 (class scrapy.item.Item())

  • Item对象表示一个从HTML页面中提取的信息内容。
  • 由Spider生成,由Item Pipeline处理。
  • Item类似字典类型,可以按照字典类型操作。

 

Scrapy爬虫提取信息的方法:

     Beautiful Soup     lxml     re     XPath Selector     CSS Selector

 

Xpath Selector:

举例

##<div id="test1">大家好!</div>

data = response.xpath('//div[@id="test1"]/text()').extract()[0]

 

##<div id="test3">我左青龙,<span id="tiger">右白虎,<ul>上朱雀,<li>下玄武。</li></ul>老牛在当中,</span>龙头在胸口。<div>

data = response.xpath('//div[@id="test3"]')

info = data.xpath('string(.)').extract()[0]

 

     CSS Selector的基本使用:(由W3C组织维护并规范)

          <HTML>.css('a::attr(href)').extract()

                         a:标签名     href:标签属性

www.w3school.com.cn/cssref/css_selectors.asp     (参考链接)

.class.intro选择 class="intro" 的所有元素。1
::selection::selection选择被用户选取的元素部分。
elementp选择所有 <p> 元素。1
element,elementdiv,p选择所有 <div> 元素和所有 <p> 元素。1
element elementdiv p选择 <div> 元素内部的所有 <p> 元素。1

 

spider中应用举例:

start_urls = ["http://bj.lianjia.com/ershoufang/pg1tt2/"]

 

def parse(self, response):

        # 获取当前页面的房屋列表
        #house_lis = response.css('.house-lst .info-panel')

        # 把结果输出到文件(在命令行中房屋标题会因为编码原因显示为乱码)

        with open("homelink.log", "wb") as f:

            ## 使用css selector进行操作

            #average_price = response.css('.secondcon.fl li:nth-child(1)').css('.botline a::text').extract_first()

            #f.write("Average Price: " + str(average_price) + "\r\n")
            #yesterday_count = response.css('.secondcon.fl li:last-child').css('.botline strong::text').extract_first()
            #f.write("Yesterday Count: " + str(yesterday_count) + "\r\n")
            #for house_li in house_lis:
            #    link = house_li.css('a::attr("href")').extract_first()            # 获取房屋的链接地址
            #    title = house_li.css('a::text').extract_first()                    # 获取房屋的标题
            #    price = house_li.css('.price .num::text').extract_first()          # 获取房屋的价格

 

 

Unit2、实例4,股票数据Scrapy爬虫

 

要求同实例3

Scrapy爬虫步骤:

  1. 创建一个工程和Spider模板
    • scrapy startproject BaiduStocks
    • cd BaiduStocks
    • scrapy genspider stocks baidu.com
    • 修改spiders/stocks.py文件
  2. 编写Spider
    • 配置stocks.py文件
    • 修改对返回页面的处理
    • 修改对新增URL爬取请求的处理
  3. 编写Item Pipeline
    • 配置pipelines.py文件
    • 定义对爬取项(Scrapy Item)的处理类
    • 配置Item_Pipelines选项(settings.py文件)
  4. 优化配置策略
    • 配置并发连接选项(settings.py文件)
      • CONCURRENT_REQUESTS     Downloader最大并发请求下载数量,默认32
      • CONCURRENT_ITEMS    Item Pipeline最大并发ITEM处理数量,默认100
      • CONCURRENT_REQUESTS_PER_DOMAIN     每个目标域名最大并发请求数量,默认8
      • CONCURRENT_REQUESTS_PER_IP     每个目标IP最大并发请求数量,默认0,非0有效
  5. 执行程序
    • scrapy crawl stocks

 

spider代码:

(stocks.py文件源代码)

# -*- coding: utf-8 -*-

import scrapy

import re

 

 

class StocksSpider(scrapy.Spider):

    name = "stocks"

    start_urls = ['http://quote.eastmoney.com/stocklist.html']

 

    def parse(self, response):

        for href in response.css('a::attr(href)').ectract():

            try:

                stock = re.findall(r'[s][hz]\d{6}', href)[0]

                url = 'https://gupiao.baidu.com/stock/' + stock + '.html'

                yield scrapy.Request(url, callback=self.parse_stock)

                #此处callback 给出处理该Url 所对应的函数

            except:

                continue

 

    def parse_stock(self, response):

        infoDict = {}

        stockInfo = response.css('.stock-bets')

        name = stockInfo.css('.bets-name').extract()[0]

        keyList = stockInfo.css('dt').extract()

        valueList = stockInfo.css('dd').extract()

        for i in range(len(keyList)):

            key = re.findall(r'>.*</dt>', keyList[i])[0][1:-5]

            try:

                val = re.findall(r'\d+\.?.*</dd>', valueList[i])[0][0:-5]

            except:

                val = '--'

        infoDict.update({'股票名称': re.findall('\s.*\(',name)[0].split()[0]+\

        re.findall('\>.*\<', name)[0][1:-1]})

        #使用yield,将结果封装成Item类,传给ItemPipeline

        yield infoDict

 

pipelines.py文件源代码:

# -*- coding: utf-8 -*-

 

# Define your item pipelines here

#

# Don't forget to add your pipeline to the ITEM_PIPELINES setting

# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html

 

 

class BaidustocksPipeline(object):

    def process_item(self, item, spider):

        return item

 

class BaidustocksInfoPipeline(object):

    #爬虫启动时Pipeline对应的方法

    def open_spider(self, spider):

        self.f = open('BaiduStockInfo.txt', 'w')

 

    #爬虫关闭时Pipeline对应的方法

    def close_spider(self, spider):

        self.f.close()

 

    #对每一个Item进行处理时对应的方法:主体函数

    def process_item(self, item, spider):

        try:

            line = str(dict(item)) + '\n'

            self.f.write(line)

        except:

            pass

        return item

 

 

settings.py文件中被修改的区域:

 

- # Configure item pipelines

- # See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html

- ITEM_PIPELINES = {

-     'BaiduStocks.pipelines.BaidustocksInfoPipeline': 300,

- }

 

 

 

Unit3、扩展

 

表单提交、爬取周期、入库存储

requests-bs4-re          

scrapy                         +               PhantomJS

 

scrapyd-*          https://pypi.python.org

 

Scrapy 爬虫的应用展望

  • 普通价值:
    • 基于Linux,7*24,稳定输出
    • 商业级部署和应用(scrapyd-*)
    • 千万规模内URL爬取、内容分析和存储
  • 高阶价值:
    • 基于docker,虚拟化部署
    • 中间件扩展,增加调度和监控
    • 各种反爬虫对抗技术

 

注: 可看慕课或b站上 嵩天老师讲的python网络爬虫与信息提取课程

         本文为视频内容  转载自https://blog.youkuaiyun.com/youyinyou/article/details/77745507

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值