Module: HeaderDetect

Extended by:
HeaderDetect
Included in:
HeaderDetect, TxtBook
Defined in:
lib/header_detect.rb

Overview

HeaderDetect

HeaderDetect模块提供对标题的检测

文档结构信息分析

 一本书在编排的时候会有自己的结构信息,这些结构信息通常通过卷、篇、部分、章(回)节等表述,也会使用序号的方式表述。总体上可以分为以下几种:
1. 文本描述(text): 按卷、部分(篇)、章(回)、节等文字表述
2. 数字描述(digital): 所有结构信息都是按照数字序号表示,比如 1 xxxxx; 1.1 xxxxx
3. 混合描述(hybrid):章按照文字表述,节按照序号表示,比如 1.1 xxxxxx
 根据不同的类型,对结构信息的提取采用不同的处理手段。

有效的标题信息应该符合以下规则:

1. 标题应该不包含完整的句子(应该不包含句子分隔符,例如“。")
2. 应该包含结构信息表述,具体如下:
  文本描述:
   卷:  以"第xxx卷"开始
        以"卷"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
        以"volume"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
   部分(篇): 以"第xxx部"或"第xxx篇"开始
             以"part"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
   章(回): 以"第xxx章"或"第xxx回"开始
            以"chapter"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
   节:  以"第xxx节"开始
   前言: 以"前"开始,以"言"结束,中间加入空白字符。例如"前言","前  言"等。
         以"序"开始,以"言"结束,中间加入空白字符。例如"序言","序  言"等。
         单个"序"
         以"序"或"序言"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
        "preface"
        "foreword"
         以"preface"或"foreword"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
   索引: 以"索"开始,以"引"结束,中间加入空白字符。例如"索引","索  引"等。
         以"索引"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
        "index"
         以"index"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
   附录: 以"附"开始,以"录"结束,中间加入空白字符。例如"附录","附  录"等。
         以"附录"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
        "appendix"
         以"appendix"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
   术语: 以"术"开始,以"语"结束,中间加入空白字符。例如"术语","术  语"等。
         以"术语"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等
        "glossary"
         以"glossary"开始,后面跟序号表述方式,例如 “I”,“Ⅱ”,“1”等

  数字描述:
    以数字序号层级表达,数字序号和标题内容之间有空白字符分隔。例如"1 管理的概念", "1.1 定义", "1.1.1 管理"等。

Constant Summary collapse

HEAD_TYPES =
[:volume,:part,:chapter,:section,:preface,:appendix,:index,:glossary]

Instance Method Summary collapse

Instance Method Details

#guess_appendix?(text) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
# File 'lib/header_detect.rb', line 110

def guess_appendix?(text)
  return false if valid_title?(text)
  return true if text =~ /^附\s*录$/
  return true if text =~ /^附\s*录\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIiA-Za-z]/
  text = text.downcase
  return true if text =~ /^appendix$/
  return true if text =~ /^appendix\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIiA-Za-z]/
end

#guess_chapter?(text) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
79
80
81
# File 'lib/header_detect.rb', line 76

def guess_chapter?(text)
  return false if valid_title?(text)
  return true if text =~ /^第.{1,4}[章回则讲]/
  text = text.downcase
  return true if text =~ /^chapter\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
end

#guess_digital_header?(text) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/header_detect.rb', line 138

def guess_digital_header?(text)
  return false if valid_title?(text)
  matcher = text.match(/(^\d+(\.\d)*\s)(.*)/)
  if matcher
    return false if matcher[3].length == 0
    levels = matcher[1].split(".")
    return false if levels[0].to_i > 99
    case levels.count
    when 1
      "chapter".to_sym
    else
      "sect#{levels.count - 1}".to_sym
    end
  end
end

#guess_digital_section?(text) ⇒ Boolean

Returns:

  • (Boolean)


128
129
130
131
132
133
134
135
136
# File 'lib/header_detect.rb', line 128

def guess_digital_section?(text)
  return false if valid_title?(text)
  matcher = text.match(/^(\d+\.)+[\d]\s*(.*)/)
  if matcher
    return false if matcher[2].length == 0
    level = matcher[0].split(".").count - 1
    "sect#{level}".to_sym
  end
end

#guess_glossary?(text) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
122
123
124
125
126
# File 'lib/header_detect.rb', line 119

def guess_glossary?(text)
  return false if valid_title?(text)
  return true if text =~ /^术\s*语$/
  return true if text =~ /^术\s*语\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
  text = text.downcase
  return true if text =~ /^glossary$/
  return true if text =~ /^glossary\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
end

#guess_header?(text) ⇒ Boolean

Returns:

  • (Boolean)


154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/header_detect.rb', line 154

def guess_header?(text)
  return :volume if guess_volume?(text)
  return :part if guess_part?(text)
  return :chapter if guess_chapter?(text)
  return :sect1 if guess_section?(text)
  return :preface if guess_preface?(text)
  return :appendix if guess_appendix?(text)
  return :index if guess_index?(text)
  return :glossary if guess_glossary?(text)
  if type = guess_digital_section?(text)
    return type
  end
end

#guess_index?(text) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
104
105
106
107
108
# File 'lib/header_detect.rb', line 101

def guess_index?(text)
  return false if valid_title?(text)
  return true if text =~ /^索\s*引$/
  return true if text =~ /^索\s*引\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
  text = text.downcase
  return true if text =~ /^index$/
  return true if text =~ /^index\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
end

#guess_part?(text, options = {}) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
72
73
74
# File 'lib/header_detect.rb', line 69

def guess_part?(text,options={})
  return false if valid_title?(text)
  return true if text =~ /^第.{1,3}[部篇]/
  text = text.downcase
  return true if text =~ /^part\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
end

#guess_preface?(text) ⇒ Boolean

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/header_detect.rb', line 88

def guess_preface?(text)
  return false if valid_title?(text)
  return true if text =~ /^前\s*言$/
  return true if text =~ /^序\s*言$/
  return true if text =~ /^序$/
  return true if text =~ /^序[言]\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
  text = text.downcase
  return true if text =~ /^preface$/
  return true if text =~ /^preface\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
  return true if text =~ /^foreword$/
  return true if text =~ /^foreword\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
end

#guess_section?(text) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
86
# File 'lib/header_detect.rb', line 83

def guess_section?(text)
  return false if valid_title?(text)
  return true if text =~ /^第.{1,3}[节]/
end

#guess_volume?(text, options = {}) ⇒ Boolean

Returns:

  • (Boolean)


62
63
64
65
66
67
# File 'lib/header_detect.rb', line 62

def guess_volume?(text,options={})
  return false if valid_title?(text)
  return true if (text =~ /^第.{1,3}卷/ || text =~ /^卷\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/)
  text = text.downcase
  return true if text =~ /^volume\s*[\dⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹIi]/
end

#hav_complete_sentence?(text) ⇒ Boolean

判断包含完整的句子。

Returns:

  • (Boolean)


52
53
54
55
# File 'lib/header_detect.rb', line 52

def hav_complete_sentence?(text)
  text = text.gsub(/^\d+(\.\d)*\s/,'')
  text =~ /[\.。!\?!?]/
end

#valid_title?(text) ⇒ Boolean

Returns:

  • (Boolean)


57
58
59
60
# File 'lib/header_detect.rb', line 57

def valid_title?(text)
  text = text.gsub(/^\d+(\.\d)*\s/,'')
  text =~ /[\.。]/
end