PDF数据提取------3.解析Demo
1.PDF中文本字符串格式中关键值信息抓取(已完成)
简介:这种解析比较传统最简单主要熟练使用Regular Expression做语义识别和验证.例如抓取下面红色圈内关键信息
- string mettingData=GetMeetingData();
- public string GetMeetingData()
- {
- string patternAll = @"(?<NDAandCAMDate>会\s*议\s*.{2,15}\d{2,4}\s*年\s*\d{1,2}\s*月\s*\d{1,2}\s*日.{0,15})";
- PdfAnalyzer pa = new PdfAnalyzer();
- PDFNet.Initialize();
- PDFDoc doc = new PDFDoc(item);
- doc.InitSecurityHandler();
- List<PdfString> foundAll = pa.RegexSearchAllPages(doc, patternAll);
- List<string> patternFilter = new List<string>();
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?(上午)?(?<hour>\d{1,2})(\:|点|时)(?<minute>\d{1,2})");
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?下午(?<hour>\d{1,2})(\:|点|时)(?<minute>\d{1,2})");
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?(上午)?(?<hour>\d{1,2})点半");
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?下午(?<hour>\d{1,2})点半");
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?(上午)?(?<hour>\d{1,2})(点|时)");
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日((\(|\()(星期|周)(一|二|三|四|五|六|七)(\)|\)))?下午(?<hour>\d{1,2})(点|时)");
- patternFilter.Add(@"(?<year>\d{2,4})年(?<month>\d{1,2})月(?<day>\d{1,2})日");
- return GetMeetingDateFilter(foundAll, patternAll);
- }
- private string GetMeetingDateFilter(List<PdfString> foundAll, List<string> patternAll)
- {
- string meetingDate = " ";
- Match ma = null;
- string result = string.Empty;
- foreach (PdfString pdfString in foundAll)
- {
- result = pdfString.ToString().Replace(" ", "");
- for (int i = ; i < patternAll.Count; i++)
- {
- ma = (new Regex(patternAll[i])).Match(result);
- if (ma.Success)
- {
- if (IsValid(ma))
- return meetingDate;
- else
- meetingDate = " ";
- }
- }
- }
- return meetingDate;
- }
注解:
a.第一次通过通过 pa.RegexSearchAllPages(doc, patternAll);搜索所有关于时间数据信息
b.第二次通过正则匹配获取带有关键词信息Meeting Data
2.PDF类似表格形式关键值数据抓取。(已完成)
简介:这种格式需要用的封装数据结构PdfString类和PdfAnalyzer类,根据给定关键词在指定范围提取数据,例如提取下面数据。
- private string GetPremium(string path, string ricCode)
- {
- string result = string.Empty;
- PDFDoc doc = null;
- try
- {
- PDFNet.Initialize();
- doc = new PDFDoc(path);
- doc.InitSecurityHandler();
- if (doc == null)
- {
- string msg = string.Format("can't load pdf to doc = new PDFDoc({0}); ", path);
- Logger.Log(msg, Logger.LogType.Error);
- return result;
- }
- int x1 = ;
- int y1 = ;
- PdfAnalyzer pa = new PdfAnalyzer();
- List<PdfString> listX1 = pa.RegexSearchAllPages(doc, ricCode);
- List<PdfString> listY1 = pa.RegexSearchAllPages(doc, @"[P|p]remium");
- List<PdfString> listResult = pa.RegexSearchAllPages(doc, @"(?<Result>\d+\.\d+\%)");
- if (listX1.Count == || listY1.Count == || listResult.Count == )
- {
- string msg = string.Format("({0}),([P|p]remium) exist missing value ,so Gearing is empty value.", ricCode);
- Logger.Log(msg, Logger.LogType.Warning);
- return result;
- }
- x1 = System.Convert.ToInt32(listX1[].Position.x1);
- y1 = System.Convert.ToInt32(listY1[].Position.y1);
- int subX1 = ;
- int subY1 = ;
- //use Gearing position (x1,y1) to get the right result value
- foreach (var item in listResult)
- {
- subX1 = x1 - System.Convert.ToInt32(item.Position.x1);
- if (subX1 < ) subX1 = - subX1;
- subY1 = y1 - System.Convert.ToInt32(item.Position.y1);
- if (subY1 < ) subY1 = - subY1;
- if (subX1 <= && subY1 <= )
- {
- result = item.ToString().Replace("%", "");
- return result;
- }
- }
- Logger.Log(string.Format("stock code:{0},extract premium failed .", ricCode), Logger.LogType.Error);
- return result;
- }
- catch (Exception ex)
- {
- string msg = string.Format("PDF analysis failed for " + ricCode + "! Action: Need manually input gearing and premium \r\n error msg:{0}", ex.Message);
- Logger.Log(msg, Logger.LogType.Warning);
- return result;
- }
- }
3.需要PDF中大量数据转换到Excel中去 (已完成)
简介:基与2的延伸,加入一个自动模糊匹配到行和列边界范围,根据位置坐标排序提取正确数据信息。如图:
- private void StartExtractFile()
- {
- List<List<string>> bulkFileFilter = null;
- List<LineFound> bulkFile = null;
- PDFNet.Initialize();
- PDFDoc doc = new PDFDoc(config.FilePath1);
- doc.InitSecurityHandler();
- string patternTitle = @"コード";
- int page = ;
- PdfString ricPosition = GetRicPosition(doc, patternTitle, page);
- if (ricPosition == null)
- return;
- string patternRic = @"\d{4}";
- string patternValue = @"(\-|\+)?\d+(\,|\.|\d)+";
- bulkFile = GetValue(doc, ricPosition, patternRic, patternValue);
- int indexOK = ;
- bulkFileFilter = FilterBulkFile(bulkFile, indexOK);
- string filePath = Path.Combine(config.OutputFolder, string.Format("Type1ExtractedFromPdf{0}.csv", DateTime.Now.ToString("dd-MM-yyyy")));
- if (File.Exists(filePath))
- File.Delete(filePath);
- XlsOrCsvUtil.GenerateStringCsv(filePath, bulkFileFilter);
- AddResult(Path.GetFileNameWithoutExtension(filePath), filePath, "type1");
- }
- private List<List<string>> FilterBulkFile(List<LineFound> bulkFile, int indexOK)
- {
- List<List<string>> result = new List<List<string>>();
- if (bulkFile == null || bulkFile.Count == )
- {
- Logger.Log("no value data extract from pdf");
- return null;
- }
- int count = bulkFile[indexOK].LineData.Count;
- List<string> line = null;
- foreach (var item in bulkFile)
- {
- if (item.LineData == null || item.LineData.Count <= )
- continue;
- line = new List<string>();
- if (item.LineData.Count.CompareTo(count) == )
- {
- foreach (var value in item.LineData)
- {
- line.Add(value.Words.ToString());
- }
- }
- else
- {
- line.Add(item.LineData[].Words.ToString());
- for (int i = ; i < count; i++)
- {
- line.Add(string.Empty);
- }
- }
- result.Add(line);
- }
- return result;
- }
- private List<LineFound> GetValue(PDFDoc doc, PdfString ricPosition, string patternRic, string patternValue)
- {
- List<LineFound> bulkFile = new List<LineFound>();
- try
- {
- List<string> line = new List<string>();
- List<PdfString> ric = null;
- //for (int i = 1; i < 10; i++)
- for (int i = ; i < doc.GetPageCount(); i++)
- {
- ric = pa.RegexExtractByPositionWithPage(doc, patternRic, i, ricPosition.Position);
- foreach (var item in ric)
- {
- LineFound lineFound = new LineFound();
- lineFound.Ric = item.Words.ToString();
- lineFound.Position = item.Position;
- lineFound.PageNumber = i;
- lineFound.LineData = pa.RegexExtractByPositionWithPage(doc, patternValue, i, item.Position, PositionRect.X2);
- bulkFile.Add(lineFound);
- }
- }
- }
- catch (Exception ex)
- {
- string msg = string.Format("\r\n ClassName: {0}\r\n MethodName: {1}\r\n Message: {2}",
- System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString(),
- System.Reflection.MethodBase.GetCurrentMethod().Name,
- ex.Message);
- Logger.Log(msg, Logger.LogType.Error);
- }
- return bulkFile;
- }
- private PdfString GetRicPosition(PDFDoc doc, string pattern, int page)
- {
- try
- {
- List<PdfString> ricPosition = null;
- ricPosition = pa.RegexSearchByPage(doc, @"コード", page);
- if (ricPosition == null || ricPosition.Count == )
- {
- 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}"));
- return null;
- }
- return ricPosition[];
- }
- catch (Exception ex)
- {
- string msg = string.Format("\r\n ClassName: {0}\r\n MethodName: {1}\r\n Message: {2}",
- System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString(),
- System.Reflection.MethodBase.GetCurrentMethod().Name,
- ex.Message);
- Logger.Log(msg, Logger.LogType.Error);
- throw;
- }
- }
- }
- struct LineFound
- {
- public string Ric { get; set; }
- public Rect Position { get; set; }
- public int PageNumber { get; set; }
- public List<PdfString> LineData { get; set; }
- }
注解:
a.由于PDF中数据坐标位置信息是基于页的所以必须按页来解析抓取数据
b.大概思路,第一次获取“コード”位置,来获取每页中Ric List的集合(获取列并排序)
c.根据每一列信息获取每一行信息(获取并排序),组合成表格信息
改进:
现在这部分还需要代码中手动干预,下一步打算加入自动识别功能,通过获取大量PDF数据自动根据位置信息组合成Table信息
4.PDF中数据保存图片格式(未完成)
想法:这种PDF文件我目前还没好的处理办法,应该需要用到图像识别方面的算法。对着这种文件格式表示我现在确实无能为力,
希望那位大神提供一些好的建议。
PDF数据提取------3.解析Demo的更多相关文章
- PDF数据提取------2.相关类介绍
1.简介 构造数据类型PdfString封装Rect类,PdfAnalyzer类中定义一些PDF解析方法. 2.PdfString类与Rect类 public class PdfString : IC ...
- Python爬虫10-页面解析数据提取思路方法与简单正则应用
GitHub代码练习地址:正则1:https://github.com/Neo-ML/PythonPractice/blob/master/SpiderPrac15_RE1.py 正则2:match. ...
- Python爬虫教程-18-页面解析和数据提取
本篇针对的数据是已经存在在页面上的数据,不包括动态生成的数据,今天是对HTML中提取对我们有用的数据,去除无用的数据 Python爬虫教程-18-页面解析和数据提取 结构化数据:先有的结构,再谈数据 ...
- 转:SQL SERVER数据库中实现快速的数据提取和数据分页
探讨如何在有着1000万条数据的MS SQL SERVER数据库中实现快速的数据提取和数据分页.以下代码说明了我们实例中数据库的“红头文件”一表的部分数据结构: CREATE TABLE [dbo]. ...
- PHP实例 表单数据插入数据库及数据提取 用户注册验证
网站在进行新用户注册时,都会将用户的注册信息存入数据库中,需要的时候再进行提取.今天写了一个简单的实例. 主要完成以下几点功能: (1)用户进行注册,实现密码重复确认,验证码校对功能. (2)注册成功 ...
- SQL 正则表达式使模式匹配和数据提取变得更容易
SQL Server 2005 正则表达式使模式匹配和数据提取变得更容易 David Banister 本文讨论: 使用正则表达式进行高效的 SQL 查询 SQL Server 2005 对正则表达式 ...
- PHP+Mysql-表单数据插入数据库及数据提取完整过程
网站在进行新用户注册时,都会将用户的注册信息存入数据库中,需要的时候再进行提取.今天写了一个简单的实例. 主要完成以下几点功能: (1)用户进行注册,实现密码重复确认,验证码校对功能. (2)注册成功 ...
- PHP+Mysql————表单数据插入数据库及数据提取
站点在进行新用户注冊时,都会将用户的注冊信息存入数据库中,须要的时候再进行提取.今天写了一个简单的实例. 主要完毕下面几点功能: (1)用户进行注冊,实现password反复确认,验证码校对功能. ( ...
- Struts2 Action接收POST请求JSON数据及其实现解析
一.认识JSON JSON是一种轻量级.基于文本.与语言无关的数据交换格式,可以用文本格式的形式来存储或表示结构化的数据. 二.POST请求与Content-Type: application/jso ...
随机推荐
- Java:编码的详解
ASCII:美国信息标准信息码,用一个字节的7为表示. ISO8859-1:拉丁码表 欧洲码表 ,用一个字节的8位表示. GB2312:中国的中文编码表. GBK:中国的中文编码表升级,融合了更多的中 ...
- 使用 tar 命令管理存档文件
tar命令用于将大型文件集汇集为一个文件(存档) tar的三种操作:c(创建存档).t(列出存档的内容).x提取存档 tar的常用选项:f(要操作的存档文件名).v(可视化操作) 创建压缩的tar存档 ...
- WebStorm 对 Mocha 完美支持。
如果你在使用 Mocha 的话,请使用 WebStorm 来运行 mocha,Webstorm可以清晰查看每个 test 的详细信息,非常直观,强烈推荐.
- Hadoop2.2.0 安装笔记
在Youtube上找到靠谱的教程:http://www.youtube.com/watch?v=WN2tJk_oL6E 同时把作者的教程下载下来放在百度云盘上了:http://pan.baidu.co ...
- hdu4185解题报告
这里我居然能自己想想到怎么建图匹配,很是不容易... 题意:这里有一片油田,但是不是纯净的,有的地方是水,现在有一个捞石油的机器,但是这个机器捞的范围是固定的,是2*1的一个矩形大小,那么对于整个油田 ...
- OpenMp之sections用法
section语句是用在sections语句里用来将sections语句里的代码划分成几个不同的段 #pragma omp [parallel] sections [子句] { #pragma ...
- ccnu-线段树联系-单点更新2-B
B - 单点更新2 Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status Des ...
- [HDOJ1078]FatMouse and Cheese(记忆化搜索)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1078 题意:给出n, k,然后给出n*n的地图,(下标0~n-1),有一只老鼠从(0,0)处出发,只能 ...
- Codeforces Round #174 (Div. 1)A
题不怎么难,按线段树的解法 就是延迟标记,更新 因为找错找了N久 记一篇吧 向下更新时把+=写成了= 还做在了2W组的数据上 那个错找得真费劲.. #include <iostream> ...
- Node Security
发一个很早之前做的一个小东西-安全管理软件-可以对U盘进行管理,对后台程序进行扫描.分析!