iOS 簡(jiǎn)單分割小說(shuō)章節(jié)

基本的思路:

  1. 用正則獲取章節(jié)名稱所在的位置(NSRange)
  2. 結(jié)合下一章的章節(jié)名的位置拿到本章內(nèi)容信息

具體實(shí)現(xiàn)方法

/**
 提取章節(jié)的NSRange信息

 @param content 文本內(nèi)容
 @return `range字符串`數(shù)組
 */
+ (NSArray<NSTextCheckingResult *> *)extractChapterListWithContent:(NSString *)content{
    
    NSString* regPattern = @"(\\s)+[第]{0,1}[0-9一二三四五六七八九十百千萬(wàn)]+[章回節(jié)卷集幕計(jì)][ \t]*(\\S)*";
    NSError* error = NULL;
    NSRegularExpression* regExp = [NSRegularExpression regularExpressionWithPattern:regPattern
                                                                            options:NSRegularExpressionCaseInsensitive
                                                                              error:&error];
    
    return [regExp matchesInString:content options:NSMatchingReportCompletion range:NSMakeRange(0, content.length)];
}

根據(jù) title Range 提取章節(jié)所需信息

/**
 根據(jù) title Range 提取章節(jié)所需信息
 
 @param content 字符串內(nèi)容
 @param maintainEmptyCharcter 是否保留空章節(jié)
 @return ChapterModel數(shù)組
 */
+ (NSArray<ChapterModel *> *)analyseTxtWithContent:(NSString *)content
                             maintainEmptyCharcter:(BOOL)maintainEmptyCharcter{
    
    NSArray<NSTextCheckingResult *> *matchResult = [self extractChapterListWithContent:content];
    NSMutableArray *chapterModels = @[].mutableCopy ;
 
    if (matchResult.count == 0) {
        ChapterModel *model = [ChapterModel new] ;
        model.title = @"內(nèi)容";
        model.contentRange = NSMakeRange(0, content.length);
        model.allContentRange = NSMakeRange(0, content.length);
        return @[model];
    }
    
    for (NSInteger i = 0; i < matchResult.count ; i++) {
        
        NSRange titleRange = matchResult[i].range;
        NSString *chapterTitle = [[content yj_substringWithRange:titleRange] trimmed];
        NVLog(@"%@",chapterTitle);
        if (i == 0) { //第0章前
            
            NSString *firstTitle = @"開(kāi)始";
            NSString *contentString = [content yj_substringWithRange:NSMakeRange(0, titleRange.location)];
            if (contentString.trimmed.length > 0 ) {
                
                ChapterModel *model2 = [ChapterModel modelWithTitle:firstTitle
                                                         titleRange:NSMakeRange(0, 0)
                                                    allContentRange:NSMakeRange(0, titleRange.location)];
                [chapterModels addObject:model2];
            }
        }
        
        if (i < matchResult.count-1) {
            
            NSRange nextRange = matchResult[i+1].range;
            if (nextRange.location > titleRange.location) {
                
                NSInteger length = nextRange.location - titleRange.location ;
                ChapterModel *model2 = [ChapterModel modelWithTitle:chapterTitle
                                                         titleRange:titleRange
                                                    allContentRange:NSMakeRange(titleRange.location, length)];
                
                [self chapterModels:chapterModels addModel:model2 content:content maintainEmpty:maintainEmptyCharcter];
            }
        }
        
        if (i == matchResult.count-1){ //最后章節(jié)
            
            ChapterModel *model2 = [ChapterModel modelWithTitle:chapterTitle
                                                     titleRange:titleRange
                                                allContentRange:NSMakeRange(titleRange.location,content.length -  titleRange.location)];
            [self chapterModels:chapterModels addModel:model2 content:content maintainEmpty:maintainEmptyCharcter];
        }
    }
    return [chapterModels copy];
}

+ (void)chapterModels:(NSMutableArray *)chapterModels
             addModel:(ChapterModel *)model
              content:(NSString *)content
        maintainEmpty:(BOOL)maintainEmptyCharcter{
    NSInteger contentLength = [[content yj_substringWithRange:model.contentRange] trimmed].length;
    //保留空章節(jié) 或者 章節(jié)有內(nèi)容
    if (maintainEmptyCharcter == YES || contentLength > 0) {
        [chapterModels addObject:model];
    }
}
添加輔助方法

新增ChapterModel類:

@interface ChapterModel : NSObject
//章節(jié)標(biāo)題
@property(nonatomic,copy)NSString *title ;
@property(nonatomic)NSRange titleRange ;
//章節(jié)內(nèi)容
@property(nonatomic)NSRange contentRange ;
//內(nèi)容(包括title)
@property(nonatomic)NSRange allContentRange;
@end 

@implementation ChapterModel

+ (instancetype)modelWithTitle:(NSString *)title
                    titleRange:(NSRange )titleRange
               allContentRange:(NSRange )allContentRange
{
    
    ChapterModel *model = [[ChapterModel alloc]init];
    
    model.title = title ;
    model.titleRange = titleRange ;
    model.allContentRange = allContentRange ;
    model.contentRange = NSMakeRange(titleRange.location + titleRange.length,
                                     allContentRange.length - titleRange.length);

    return model;
}

@end

添加NSString類別,防止substringWithRange越界

@implementation NSString (YJSafe)
//防止越界
- (NSString *)yj_substringWithRange:(NSRange)range{
    
    if (self.length >= range.location + range.length) {
        return [self substringWithRange:range];
    }
    return @"";
}

- (NSString *)trimmed{
    NSCharacterSet* whiteSpaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    return [self stringByTrimmingCharactersInSet:whiteSpaceSet];
}

@end
異步獲取
/** 
 提取章節(jié)信息
 
 @param content 文本內(nèi)容
 @param isAsync 是否是異步
 @param isNeedMaintainEmptyCharcter 是否需要提取空的章節(jié)
 @param result 返回ChapterModel數(shù)組
 */
+ (void)extractNovelWithContent:(NSString *)content
                          async:(BOOL)isAsync
          maintainEmptyCharcter:(BOOL)isNeedMaintainEmptyCharcter
                         result:(void(^)(NSArray<ChapterModel *> *models))result {
    
    if (result == nil) {  return ;}
    
    if (isAsync) {
        
        dispatch_async(dispatch_get_global_queue(0,0), ^{
            
            NSArray *models = [self analyseTxtWithContent:content maintainEmptyCharcter:isNeedMaintainEmptyCharcter];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                result(models);
            });
        });
        
    }else {
        result([self analyseTxtWithContent:content maintainEmptyCharcter:isNeedMaintainEmptyCharcter]);
    }
}
預(yù)覽:

方法調(diào)用

2017011818316novel_code.png

效果預(yù)覽


2017011872898nove_show.png

此外還需要解決的問(wèn)題:

  1. 這個(gè)正則是根據(jù)這篇文章修改的,還不能匹配第n章和章節(jié)名字多個(gè)空格的情況
  2. 有的標(biāo)題可能比較特別 ,好比【《》目錄 第二回 悟徹菩提真妙理 斷魔歸本合元神】 。 這樣匹配“第二回”所在的一行應(yīng)該比較好
  • 不過(guò)還有這樣的【《》目錄 第十一回 還受生唐王遵善果 度孤魂蕭【《》目錄 第十二回 玄奘秉誠(chéng)建大會(huì) 觀音顯象化金蟬 】 ,章節(jié)內(nèi)容直接缺失。 如果匹配所在行估計(jì)會(huì)出問(wèn)題。
  • 忽然覺(jué)得自己該惡補(bǔ)下正則的知識(shí)了。。。。

參考內(nèi)容
iOS txt小說(shuō)斷章正則表達(dá)式實(shí)現(xiàn)
TXT小說(shuō)斷章實(shí)現(xiàn)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,769評(píng)論 25 709
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 本文筆記源自這里——[實(shí)驗(yàn)樓]歡迎大家在下面交流其中有問(wèn)題的地方喜歡請(qǐng)點(diǎn)收藏,每日更新(全部已親自實(shí)踐). 一. ...
    東皇Amrzs閱讀 4,296評(píng)論 7 54
  • 7月1日開(kāi)始,進(jìn)行社群的腦洞大開(kāi)訓(xùn)練運(yùn)營(yíng)。 我當(dāng)時(shí)所具備的條件:①較為豐富的經(jīng)驗(yàn)②更多的時(shí)間③更強(qiáng)的耐心 報(bào)名通知...
    博雅大師兄閱讀 584評(píng)論 0 3
  • 數(shù)十日不見(jiàn)樓下阿婆,突然有種不詳預(yù)感。一日上下樓時(shí)隱約間聽(tīng)到聊天對(duì)話,幾天后才得知,阿婆摔倒已經(jīng)住院一個(gè)多月了,有...
    令令噠閱讀 217評(píng)論 0 0

友情鏈接更多精彩內(nèi)容