1.PDF中文本字符串格式中关键值信息抓取(已完成)

简介:这种解析比较传统最简单主要熟练使用Regular Expression做语义识别和验证.例如抓取下面红色圈内关键信息

  1. string mettingData=GetMeetingData();
  2.  
  3. public string GetMeetingData()
  4. {
  5. string patternAll = @"(?<NDAandCAMDate>会\s*议\s*.{2,15}\d{2,4}\s*年\s*\d{1,2}\s*月\s*\d{1,2}\s*日.{0,15})";
  6. PdfAnalyzer pa = new PdfAnalyzer();
  7. PDFNet.Initialize();
  8. PDFDoc doc = new PDFDoc(item);
  9. doc.InitSecurityHandler();
  10. List<PdfString> foundAll = pa.RegexSearchAllPages(doc, patternAll);
  11.  
  12. List<string> patternFilter = new List<string>();
  13. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?(上午)?(?<hour>\d{1,2})(\:|点|时)(?<minute>\d{1,2})");
  14. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?下午(?<hour>\d{1,2})(\:|点|时)(?<minute>\d{1,2})");
  15. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?(上午)?(?<hour>\d{1,2})点半");
  16. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?下午(?<hour>\d{1,2})点半");
  17. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?(上午)?(?<hour>\d{1,2})(点|时)");
  18. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?下午(?<hour>\d{1,2})(点|时)");
  19. patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日");
  20.  
  21. return GetMeetingDateFilter(foundAll, patternAll);
  22. }
  23.  
  24. private string GetMeetingDateFilter(List<PdfString> foundAll, List<string> patternAll)
  25. {
  26. string meetingDate = " ";
  27. Match ma = null;
  28. string result = string.Empty;
  29.  
  30. foreach (PdfString pdfString in foundAll)
  31. {
  32. result = pdfString.ToString().Replace(" ", "");
  33. for (int i = ; i < patternAll.Count; i++)
  34. {
  35. ma = (new Regex(patternAll[i])).Match(result);
  36. if (ma.Success)
  37. {
  38. if (IsValid(ma))
  39. return meetingDate;
  40. else
  41. meetingDate = " ";
  42. }
  43. }
  44. }
  45. return meetingDate;
  46. }

注解:

a.第一次通过通过 pa.RegexSearchAllPages(doc, patternAll);搜索所有关于时间数据信息

b.第二次通过正则匹配获取带有关键词信息Meeting Data

2.PDF类似表格形式关键值数据抓取。(已完成)

简介:这种格式需要用的封装数据结构PdfString类和PdfAnalyzer类,根据给定关键词在指定范围提取数据,例如提取下面数据。

  1. private string GetPremium(string path, string ricCode)
  2. {
  3. string result = string.Empty;
  4. PDFDoc doc = null;
  5. try
  6. {
  7. PDFNet.Initialize();
  8. doc = new PDFDoc(path);
  9. doc.InitSecurityHandler();
  10.  
  11. if (doc == null)
  12. {
  13. string msg = string.Format("can't load pdf to doc = new PDFDoc({0}); ", path);
  14. Logger.Log(msg, Logger.LogType.Error);
  15. return result;
  16. }
  17.  
  18. int x1 = ;
  19. int y1 = ;
  20. PdfAnalyzer pa = new PdfAnalyzer();
  21. List<PdfString> listX1 = pa.RegexSearchAllPages(doc, ricCode);
  22. List<PdfString> listY1 = pa.RegexSearchAllPages(doc, @"[P|p]remium");
  23. List<PdfString> listResult = pa.RegexSearchAllPages(doc, @"(?<Result>\d+\.\d+\%)");
  24.  
  25. if (listX1.Count == || listY1.Count == || listResult.Count == )
  26. {
  27. string msg = string.Format("({0}),([P|p]remium) exist missing value ,so Gearing is empty value.", ricCode);
  28. Logger.Log(msg, Logger.LogType.Warning);
  29. return result;
  30. }
  31.  
  32. x1 = System.Convert.ToInt32(listX1[].Position.x1);
  33. y1 = System.Convert.ToInt32(listY1[].Position.y1);
  34.  
  35. int subX1 = ;
  36. int subY1 = ;
  37. //use Gearing position (x1,y1) to get the right result value
  38. foreach (var item in listResult)
  39. {
  40. subX1 = x1 - System.Convert.ToInt32(item.Position.x1);
  41. if (subX1 < ) subX1 = - subX1;
  42. subY1 = y1 - System.Convert.ToInt32(item.Position.y1);
  43. if (subY1 < ) subY1 = - subY1;
  44.  
  45. if (subX1 <= && subY1 <= )
  46. {
  47. result = item.ToString().Replace("%", "");
  48. return result;
  49. }
  50. }
  51.  
  52. Logger.Log(string.Format("stock code:{0},extract premium failed .", ricCode), Logger.LogType.Error);
  53. return result;
  54. }
  55. catch (Exception ex)
  56. {
  57. string msg = string.Format("PDF analysis failed for " + ricCode + "! Action: Need manually input gearing and premium \r\n error msg:{0}", ex.Message);
  58. Logger.Log(msg, Logger.LogType.Warning);
  59. return result;
  60. }
  61. }

3.需要PDF中大量数据转换到Excel中去 (已完成)

简介:基与2的延伸,加入一个自动模糊匹配到行和列边界范围,根据位置坐标排序提取正确数据信息。如图:

  1. private void StartExtractFile()
  2. {
  3. List<List<string>> bulkFileFilter = null;
  4. List<LineFound> bulkFile = null;
  5. PDFNet.Initialize();
  6. PDFDoc doc = new PDFDoc(config.FilePath1);
  7. doc.InitSecurityHandler();
  8. string patternTitle = @"コード";
  9. int page = ;
  10. PdfString ricPosition = GetRicPosition(doc, patternTitle, page);
  11. if (ricPosition == null)
  12. return;
  13.  
  14. string patternRic = @"\d{4}";
  15. string patternValue = @"(\-|\+)?\d+(\,|\.|\d)+";
  16. bulkFile = GetValue(doc, ricPosition, patternRic, patternValue);
  17. int indexOK = ;
  18. bulkFileFilter = FilterBulkFile(bulkFile, indexOK);
  19. string filePath = Path.Combine(config.OutputFolder, string.Format("Type1ExtractedFromPdf{0}.csv", DateTime.Now.ToString("dd-MM-yyyy")));
  20.  
  21. if (File.Exists(filePath))
  22. File.Delete(filePath);
  23.  
  24. XlsOrCsvUtil.GenerateStringCsv(filePath, bulkFileFilter);
  25. AddResult(Path.GetFileNameWithoutExtension(filePath), filePath, "type1");
  26. }
  27.  
  28. private List<List<string>> FilterBulkFile(List<LineFound> bulkFile, int indexOK)
  29. {
  30. List<List<string>> result = new List<List<string>>();
  31.  
  32. if (bulkFile == null || bulkFile.Count == )
  33. {
  34. Logger.Log("no value data extract from pdf");
  35. return null;
  36. }
  37. int count = bulkFile[indexOK].LineData.Count;
  38.  
  39. List<string> line = null;
  40. foreach (var item in bulkFile)
  41. {
  42. if (item.LineData == null || item.LineData.Count <= )
  43. continue;
  44.  
  45. line = new List<string>();
  46. if (item.LineData.Count.CompareTo(count) == )
  47. {
  48. foreach (var value in item.LineData)
  49. {
  50. line.Add(value.Words.ToString());
  51. }
  52. }
  53. else
  54. {
  55. line.Add(item.LineData[].Words.ToString());
  56. for (int i = ; i < count; i++)
  57. {
  58. line.Add(string.Empty);
  59. }
  60. }
  61. result.Add(line);
  62. }
  63.  
  64. return result;
  65. }
  66.  
  67. private List<LineFound> GetValue(PDFDoc doc, PdfString ricPosition, string patternRic, string patternValue)
  68. {
  69. List<LineFound> bulkFile = new List<LineFound>();
  70. try
  71. {
  72. List<string> line = new List<string>();
  73. List<PdfString> ric = null;
  74.  
  75. //for (int i = 1; i < 10; i++)
  76. for (int i = ; i < doc.GetPageCount(); i++)
  77. {
  78. ric = pa.RegexExtractByPositionWithPage(doc, patternRic, i, ricPosition.Position);
  79. foreach (var item in ric)
  80. {
  81. LineFound lineFound = new LineFound();
  82. lineFound.Ric = item.Words.ToString();
  83. lineFound.Position = item.Position;
  84. lineFound.PageNumber = i;
  85. lineFound.LineData = pa.RegexExtractByPositionWithPage(doc, patternValue, i, item.Position, PositionRect.X2);
  86. bulkFile.Add(lineFound);
  87. }
  88. }
  89. }
  90. catch (Exception ex)
  91. {
  92. string msg = string.Format("\r\n ClassName: {0}\r\n MethodName: {1}\r\n Message: {2}",
  93. System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString(),
  94. System.Reflection.MethodBase.GetCurrentMethod().Name,
  95. ex.Message);
  96. Logger.Log(msg, Logger.LogType.Error);
  97. }
  98.  
  99. return bulkFile;
  100. }
  101.  
  102. private PdfString GetRicPosition(PDFDoc doc, string pattern, int page)
  103. {
  104. try
  105. {
  106. List<PdfString> ricPosition = null;
  107. ricPosition = pa.RegexSearchByPage(doc, @"コード", page);
  108. if (ricPosition == null || ricPosition.Count == )
  109. {
  110. Logger.Log(string.Format("there is no ric title found by using pattern:{0} to find the ric title ,in the page:{1} of the pdf:{2}"));
  111. return null;
  112. }
  113.  
  114. return ricPosition[];
  115. }
  116. catch (Exception ex)
  117. {
  118. string msg = string.Format("\r\n ClassName: {0}\r\n MethodName: {1}\r\n Message: {2}",
  119. System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString(),
  120. System.Reflection.MethodBase.GetCurrentMethod().Name,
  121. ex.Message);
  122. Logger.Log(msg, Logger.LogType.Error);
  123. throw;
  124. }
  125. }
  126. }
  127.  
  128. struct LineFound
  129. {
  130. public string Ric { get; set; }
  131. public Rect Position { get; set; }
  132. public int PageNumber { get; set; }
  133. public List<PdfString> LineData { get; set; }
  134. }

注解:

a.由于PDF中数据坐标位置信息是基于页的所以必须按页来解析抓取数据

b.大概思路,第一次获取“コード”位置,来获取每页中Ric List的集合(获取列并排序)

c.根据每一列信息获取每一行信息(获取并排序),组合成表格信息

改进:

现在这部分还需要代码中手动干预,下一步打算加入自动识别功能,通过获取大量PDF数据自动根据位置信息组合成Table信息

4.PDF中数据保存图片格式(未完成)

想法:这种PDF文件我目前还没好的处理办法,应该需要用到图像识别方面的算法。对着这种文件格式表示我现在确实无能为力,

希望那位大神提供一些好的建议。

PDF数据提取------3.解析Demo的更多相关文章

  1. PDF数据提取------2.相关类介绍

    1.简介 构造数据类型PdfString封装Rect类,PdfAnalyzer类中定义一些PDF解析方法. 2.PdfString类与Rect类 public class PdfString : IC ...

  2. Python爬虫10-页面解析数据提取思路方法与简单正则应用

    GitHub代码练习地址:正则1:https://github.com/Neo-ML/PythonPractice/blob/master/SpiderPrac15_RE1.py 正则2:match. ...

  3. Python爬虫教程-18-页面解析和数据提取

    本篇针对的数据是已经存在在页面上的数据,不包括动态生成的数据,今天是对HTML中提取对我们有用的数据,去除无用的数据 Python爬虫教程-18-页面解析和数据提取 结构化数据:先有的结构,再谈数据 ...

  4. 转:SQL SERVER数据库中实现快速的数据提取和数据分页

    探讨如何在有着1000万条数据的MS SQL SERVER数据库中实现快速的数据提取和数据分页.以下代码说明了我们实例中数据库的“红头文件”一表的部分数据结构: CREATE TABLE [dbo]. ...

  5. PHP实例 表单数据插入数据库及数据提取 用户注册验证

    网站在进行新用户注册时,都会将用户的注册信息存入数据库中,需要的时候再进行提取.今天写了一个简单的实例. 主要完成以下几点功能: (1)用户进行注册,实现密码重复确认,验证码校对功能. (2)注册成功 ...

  6. SQL 正则表达式使模式匹配和数据提取变得更容易

    SQL Server 2005 正则表达式使模式匹配和数据提取变得更容易 David Banister 本文讨论: 使用正则表达式进行高效的 SQL 查询 SQL Server 2005 对正则表达式 ...

  7. PHP+Mysql-表单数据插入数据库及数据提取完整过程

    网站在进行新用户注册时,都会将用户的注册信息存入数据库中,需要的时候再进行提取.今天写了一个简单的实例. 主要完成以下几点功能: (1)用户进行注册,实现密码重复确认,验证码校对功能. (2)注册成功 ...

  8. PHP+Mysql————表单数据插入数据库及数据提取

    站点在进行新用户注冊时,都会将用户的注冊信息存入数据库中,须要的时候再进行提取.今天写了一个简单的实例. 主要完毕下面几点功能: (1)用户进行注冊,实现password反复确认,验证码校对功能. ( ...

  9. Struts2 Action接收POST请求JSON数据及其实现解析

    一.认识JSON JSON是一种轻量级.基于文本.与语言无关的数据交换格式,可以用文本格式的形式来存储或表示结构化的数据. 二.POST请求与Content-Type: application/jso ...

随机推荐

  1. Java:编码的详解

    ASCII:美国信息标准信息码,用一个字节的7为表示. ISO8859-1:拉丁码表 欧洲码表 ,用一个字节的8位表示. GB2312:中国的中文编码表. GBK:中国的中文编码表升级,融合了更多的中 ...

  2. 使用 tar 命令管理存档文件

    tar命令用于将大型文件集汇集为一个文件(存档) tar的三种操作:c(创建存档).t(列出存档的内容).x提取存档 tar的常用选项:f(要操作的存档文件名).v(可视化操作) 创建压缩的tar存档 ...

  3. WebStorm 对 Mocha 完美支持。

    如果你在使用 Mocha 的话,请使用 WebStorm 来运行 mocha,Webstorm可以清晰查看每个 test 的详细信息,非常直观,强烈推荐.

  4. Hadoop2.2.0 安装笔记

    在Youtube上找到靠谱的教程:http://www.youtube.com/watch?v=WN2tJk_oL6E 同时把作者的教程下载下来放在百度云盘上了:http://pan.baidu.co ...

  5. hdu4185解题报告

    这里我居然能自己想想到怎么建图匹配,很是不容易... 题意:这里有一片油田,但是不是纯净的,有的地方是水,现在有一个捞石油的机器,但是这个机器捞的范围是固定的,是2*1的一个矩形大小,那么对于整个油田 ...

  6. OpenMp之sections用法

    section语句是用在sections语句里用来将sections语句里的代码划分成几个不同的段 #pragma omp [parallel] sections [子句] {    #pragma ...

  7. ccnu-线段树联系-单点更新2-B

    B - 单点更新2 Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Des ...

  8. [HDOJ1078]FatMouse and Cheese(记忆化搜索)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:给出n, k,然后给出n*n的地图,(下标0~n-1),有一只老鼠从(0,0)处出发,只能 ...

  9. Codeforces Round #174 (Div. 1)A

    题不怎么难,按线段树的解法 就是延迟标记,更新 因为找错找了N久 记一篇吧 向下更新时把+=写成了= 还做在了2W组的数据上 那个错找得真费劲.. #include <iostream> ...

  10. Node Security

    发一个很早之前做的一个小东西-安全管理软件-可以对U盘进行管理,对后台程序进行扫描.分析!