首先看看我的项目结构:

从上面的结果图中,我们可以看出,主要用了两个库:itextsharp.dll 和 pdfbox-1.8.9.dll,dll文件夹存放引用的库,handles文件夹存放抽取的处理代码,lib文件夹中,相当于数据库中的DBHelp类的作用。model文件夹就不用介绍了,大家都知道。

我们从大的逻辑开始介绍,TitleHandle类中有一个方法:

从此方法可以看出,它接收两个参数:block和isTrainModel,返回 HandleResult类型。

我们先来看看Block的定义:

块由行构成,我们再看看Line的定义:

行由单词构成,再来看Word定义:

它其实是一个词的集合,WordMeta是一个单词的信息,它下面还有一层结构 WordInfo类,这个类是最基础的类,它代表了pdf文档中一个字符信息,底层基础决定上层建筑:

   public class WordInfo
{
/// <summary>
/// x坐标
/// </summary>
public float X { set; get; }
/// <summary>
/// y坐标
/// </summary>
public float Y { set; get; } public int XSize { set; get; } public int YSize { get; set; } public float XDirAdj { set; get; } public float YDirAdj { set; get; } /// <summary>
/// 字号
/// </summary>
public float FontSize { set; get; } public float Xscale { set; get; } public float Yscale { set; get; }
/// <summary>
/// 高度
/// </summary>
public float Height { set; get; } /// <summary>
/// 空格大小
/// </summary>
public float Space { set; get; }
/// <summary>
/// 宽度
/// </summary>
public float Width { set; get; }
/// <summary>
/// 子字体
/// </summary>
public string Subfont { set; get; }
/// <summary>
/// 基本字体
/// </summary>
public string Basefont { set; get; }
/// <summary>
/// 是否加粗
/// </summary>
public bool IsBold { set; get; }
/// <summary>
/// 是否倾斜
/// </summary>
public bool IsItalic { set; get; }
/// <summary>
/// 单词
/// </summary>
public string Word { set; get; } public override string ToString()
{
return "String[" + this.XDirAdj + ","
+ this.YDirAdj
+ " fs=" + this.FontSize
+ " xscale=" + this.Xscale
+ " isBold=" + this.IsBold
+ " space=" + this.Space
+ " isItalic=" + this.IsItalic
+ "xSize" + this.XSize
+ "ySize" + this.YSize
+ " width=" + this.Width + "]"
+ this.Word;
}
/// <summary>
/// 计算当前字符和lastChunk的距离
/// </summary>
/// <param name="lastChunk"></param>
/// <returns></returns>
public float DistanceFromEndOf(WordInfo lastChunk)
{
return this.X - lastChunk.X - lastChunk.Width;
} }

这个类包括了字符的位置,大小,粗细等等信息。这些信息是基础当中的基础,因此非常重要,给我们判断一个块是否是标题,提供了依据,相当于国之宪法。

从我解剖出来的结构看,解析出pdf标题,关键有两点:

第一,如何正确地划分块,把具有相同格式的多行文字划分到一个块中,这样就形成了一个块的字典集合,也就是Block类中的字典类型:Dictionary<int, List<WordMeta>>。

分块也有难点,有很多上标和下标的句子,也有很多非常相似的块,可能分错。比如标题的块和作者的块,文字格式如果非常接近的话,就很容易把作者和标题划分到同一个块中,这给后面的工作带来了麻烦,以至于提取了错误的标题。

第二,如何从众多的块中筛选出标题。

此处也采取了很多筛选策略。

1、根据块长度,淘汰字符长度太短的。

2、根据块位置,淘汰位置太偏的。

3、评分机制,根据块的特征信息,计算出一个0-1之间的数值来,然后选取第一名和第二名的块。

4、在第一名和第二名之间选择。根据它们的位置,字符长度,分值,块的高度,块所包含的单词数等来判断。

c#抽取pdf文档标题(1)的更多相关文章

  1. c#抽取pdf文档标题——前言

    由于工作的需要,研究c#抽取pdf文档标题有3个月了.这项工作是一项"伟大而艰巨"的任务.应该是我目前研究工作中最长的一次.我觉得在长时间忙碌后,应该找些时间,把自己的心路历程归纳 ...

  2. c#抽取pdf文档标题(3)

    上一篇介绍了整体流程以及利用库读取pdf内容形成字符集合.这篇着重介绍下,过滤规则,毕竟我们是使用规则过滤,最后得到标题的. 首先看归一化处理,什么是归一化呢?就是使结果始终处于0-1之间(包括0,1 ...

  3. c#抽取pdf文档标题(2)

    public class IETitle { public static List<WordInfo> WordsInfo = new List<WordInfo>(); pr ...

  4. c#抽取pdf文档标题(4)——机器学习以及决策树

    我的一位同事告诉我,pdf抽取标题,用机器学习可以完美解决问题,抽取的准确率比较高.于是,我看了一些资料,就动起手来,实践了下. 我主要是根据以往历史块的特征生成一个决策树,然后利用这棵决策树,去判断 ...

  5. Python处理Excel和PDF文档

    一.使用Python操作Excel Python来操作Excel文档以及如何利用Python语言的函数和表达式操纵Excel文档中的数据. 虽然微软公司本身提供了一些函数,我们可以使用这些函数操作Ex ...

  6. C#给PDF文档添加文本和图片页眉

    页眉常用于显示文档的附加信息,我们可以在页眉中插入文本或者图形,例如,页码.日期.公司徽标.文档标题.文件名或作者名等等.那么我们如何以编程的方式添加页眉呢?今天,这篇文章向大家分享如何使用了免费组件 ...

  7. 将w3cplus网站中的文章页面提取并导出为pdf文档

    最近在看一些关于CSS3方面的知识,主要是平时看到网页中有很多用CSS3实现的很炫的效果,所以就打算系统的学习一下.在网上找到很多的文章,但都没有一个好的整理性,比较凌乱.昨天看到w3cplus网站中 ...

  8. PDF2SWF转换只有一页的PDF文档,在FlexPaper不显示解决方法

    问题:PDF2SWF转换只有一页的PDF文档,在FlexPaper不显示! FlexPaper 与 PDF2SWF 结合是解决在线阅读PDF格式文件的问题的,多页的PDF文件转换可以正常显示,只有一页 ...

  9. 【PDF】java使用Itext生成pdf文档--详解

    [API接口]  一.Itext简介 API地址:javadoc/index.html:如 D:/MyJAR/原JAR包/PDF/itext-5.5.3/itextpdf-5.5.3-javadoc/ ...

随机推荐

  1. angular ng build --prod 打包报错解决方案

    使用以下代码  就不报错了 ng build --prod --no-extract-license    打包命令 使用以下代码  就不报错了 ng build --prod --no-extrac ...

  2. 4、flask之分页插件的使用、添加后保留原url搜索条件、单例模式

    本篇导航: flask实现分页 添加后保留原url搜索条件 单例模式 一.flask实现分页 1.django项目中写过的分页组件 from urllib.parse import urlencode ...

  3. Shiro 核心功能案例讲解 基于SpringBoot 有源码

    Shiro 核心功能案例讲解 基于SpringBoot 有源码 从实战中学习Shiro的用法.本章使用SpringBoot快速搭建项目.整合SiteMesh框架布局页面.整合Shiro框架实现用身份认 ...

  4. CodeForces - 740C

    这题是思维考察.由于区间个数可能会很多,暴力完全没法下手.首先要明确区间长度最小的就决定了最后的答案,因为最小区间必须要要从0开始到区间长度减1才能满足让mex最大.接下来就是考虑如何填充数组才能让所 ...

  5. ElasticSearch AggregationBuilders java api常用聚会查询

    以球员信息为例,player索引的player type包含5个字段,姓名,年龄,薪水,球队,场上位置.index的mapping为: "mappings": { "pl ...

  6. hadoop源码调试

    原文地址:http://www.cnblogs.com/end/archive/2011/04/26/2029497.html 在使用hadoop的时候,可能遇到各种各样的问题,然而由于hadoop的 ...

  7. eclipse hadoop1.2.0配置及wordcount运行

    "error: failure to login"问题 http://www.cnblogs.com/xia520pi/archive/2012/05/20/2510723.htm ...

  8. 如何在模拟器里体验微软HoloLens

    众所周知,微软的HoloLens以及MR设备售价都比较高,这让不少感兴趣的朋友们望而却步,本篇教程将向大家介绍如何在模拟器里体验传说中的HoloLens. 1.需要准备的硬件: 智能手机一台(WP.A ...

  9. 安装sphinx和coreseek

    sphinx简介 Sphinx是由俄罗斯人Andrew Aksyonoff开发的一个全文检索引擎.意图为其他应用提供高速.低空间占用.高结果 相关度的全文搜索功能.Sphinx可以非常容易的与SQL数 ...

  10. R语言︱文本挖掘——jiabaR包与分词向量化的simhash算法(与word2vec简单比较)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- <数据挖掘之道>摘录话语:虽然我比 ...