PDFデータ抽出------2.関連クラスの紹介

25675 ワード

1.概要
データ型PdfStringパッケージRectクラスを構築し、PdfAnalyzerクラスでPDF解析方法を定義します.
 
2.PdfStringクラスとRectクラス
public class PdfString : IComparable<PdfString>

    {

        public string Words { get; set; }

        public Rect Position { get; set; }

        public int PageNumber { get; set; }



        public PdfString(string str, Rect pos, int pageNum)

        {

            this.Words = str;

            this.Position = pos;

            this.PageNumber = pageNum;

        }



        public override string ToString()

        {

            return this.Words;

        }



        public static PdfStringComparer GetComparer()

        {

            return new PdfString.PdfStringComparer();

        }



        public int CompareTo(PdfString rhs)

        {

            return this.Position.x2.CompareTo(rhs.Position.x2);

        }



        /// <summary>

        ///comparer by Horizontal or vertical 

        /// </summary>

        /// <param name="rhs"></param>

        /// <param name="which">comparer type</param>

        /// <returns></returns>

        public int CompareTo(PdfString rhs, PdfString.PdfStringComparer.ComparisonType which)

        {

            switch (which)

            {

                case PdfStringComparer.ComparisonType.Horizontal:

                    return this.Position.x2.CompareTo(rhs.Position.x2);

                case PdfStringComparer.ComparisonType.Vertical:

                    return this.Position.y2.CompareTo(rhs.Position.y2);

            }



            return 0;

        }



        /// <summary>

        /// for comparer custom comparer type

        /// </summary>

        public class PdfStringComparer : IComparer<PdfString>

        {

            private PdfString.PdfStringComparer.ComparisonType whichComparison;



            public enum ComparisonType { Horizontal, Vertical };



            public int Compare(PdfString lhs, PdfString rhs)

            {

                return lhs.CompareTo(rhs, whichComparison);

            }



            public PdfString.PdfStringComparer.ComparisonType WhichComparison

            {

                get { return whichComparison; }

                set { whichComparison = value; }

            }

        }

    }
public class Rect

    {

        public Rect();

        public Rect(Obj rect);

        public Rect(double x1, double y1, double x2, double y2);



        public double x1 { get; set; }

        public double x2 { get; set; }

        public double y1 { get; set; }

        public double y2 { get; set; }



        public void __dtor();

        public void Attach(Obj obj);

        public bool Contains(double x, double y);

        public void Get(ref double out_x1, ref double out_y1, ref double out_x2, ref double out_y2);

        public double Height();

        public void Inflate(double amount);

        public void Inflate(double x, double y);

        public bool IntersectRect(Rect rect1, Rect rect2);

        public void Normalize();

        public static Rect op_Assign(Rect lr, Rect rr);

        public void Set(Rect p);

        public void Set(double x1, double y1, double x2, double y2);

        public bool Update();

        public bool Update(Obj obj);

        public double Width();

    }

3.PdfStringクラスについて
    1.パッケージRect理由
a.Rectというクラスは粒度が小さすぎて、重要な情報を検索するデータ構造を保存できるクラスが必要で、意味に基づいて重要な情報を二次的に識別するために準備する必要がある.
b.Words属性各検索結果値を保存する
c.Rect:結果左上隅座標(x 1,y 1)右下隅座標(x 2,y 2)情報を保存
d.PageNumber:データが存在するページ番号は、PDFの座標が各ページに対してあるため、ページ番号がデータを位置決めするまで必要となる.  
    2.IComparableインタフェースを実装し、埋め込みクラスPdfStringComparerを追加
a.座標解析によるPDFでデータ情報を取得するのは規則的ではなく、データをキャプチャするのは一定の規則に従って保存されるのではなく、雑然としているからである.
b.IComparableインタフェースを単純に実装する場合、Position属性に従って1つの方法を選択して結果セットのソートを得ることができ、IComparableを実装することに注意する
1つの固定ソート方式しか選択できず、状況に応じてソート方式をカスタマイズできないため、PdfStringクラスに埋め込みクラスPdfStringComparerを導入し、使用する
x 1またはx 2座標を基準としてHorizontal位置座標で結果セットをソートし、逆にVerticalに従います.
 
4.PdfAnalyzerクラスについて
 
public enum PositionRect { X1, Y1, X2, Y2 }



public class PdfAnalyzer

{

    public List<PdfString> RegexSearchAllPages(PDFDoc doc, string pattern)

    {

        return RegexSearch(doc, pattern, false, -1, -1, true);

    }



    public List<PdfString> RegexSearchByPageRange(PDFDoc doc, string pattern, int startPage, int endPage)

    {

        if (endPage > doc.GetPageCount())

            throw new Exception("endPage out of MaxRange of pdf.");



        if (startPage < 1)

            throw new Exception("startPage out of MixRange of pdf.");



        if (startPage > endPage)

            throw new Exception("pageRange is invalid.");



        return RegexSearch(doc, pattern, false, startPage, endPage, true);

    }



    public List<PdfString> RegexSearchByPage(PDFDoc doc, string pattern, int pageIndex)

    {

        if (pageIndex > doc.GetPageCount())

            throw new Exception("pageIndex out of MaxRange of pdf.");



        if (pageIndex < 1)

            throw new Exception("pageIndex out of MixRange of pdf.");



        return RegexSearch(doc, pattern, false, pageIndex, pageIndex, true);

    }



    public List<PdfString> RegexSearch(PDFDoc doc, string pattern, bool ifWholeWord, int startPage, int endPage, bool ignoreCase)

    {

        List<PdfString> result = new List<PdfString>();

        Int32 page_num = 0;

        string result_str = "";

        string ambient_string = "";

        Highlights hlts = new Highlights();



        Int32 mode = (Int32)(TextSearch.SearchMode.e_reg_expression | TextSearch.SearchMode.e_highlight);

        if (ifWholeWord) mode |= (Int32)TextSearch.SearchMode.e_whole_word;

        if (ignoreCase) mode |= (Int32)TextSearch.SearchMode.e_case_sensitive;



        int pageCount = doc.GetPageCount();

        if (endPage > pageCount) endPage = pageCount;



        TextSearch txt_search = new TextSearch();

        txt_search.Begin(doc, pattern, mode, startPage, endPage);



        while (true)

        {

            TextSearch.ResultCode code = txt_search.Run(ref page_num, ref result_str, ref ambient_string, hlts);



            if (code == TextSearch.ResultCode.e_found)

            {

                hlts.Begin(doc);

                double[] box = null;

                string temp = result_str;



                while (hlts.HasNext())

                {

                    box = hlts.GetCurrentQuads();

                    if (box.Length != 8)

                    {

                        hlts.Next();

                        continue;

                    }



                    result.Add(new PdfString(result_str, new Rect(box[0], box[1], box[4], box[5]), page_num));

                    hlts.Next();

                }

            }

            else if (code == TextSearch.ResultCode.e_done)

            {

                break;

            }

        }



        return result;

    }



    public List<PdfString> RegexExtractByPositionWithPage(PDFDoc doc, string pattern, int pageIndex, Rect rect, PositionRect positionRect = PositionRect.Y2, double range = 2.0)

    {

        return GetNearbyPdfString(RegexSearchByPage(doc, pattern, pageIndex), rect, positionRect, range);

    }



    public List<PdfString> GetNearbyPdfString(List<PdfString> pdfStringAll, Rect rect, PositionRect positionRect, double range)

    {

        List<PdfString> pdfStringFilter = new List<PdfString>();



        foreach (var pdf in pdfStringAll)

        {

            if (pdf == null)

                continue;



            if (GetRange(pdf.Position, rect, positionRect) > range)

                continue;



            pdfStringFilter.Add(pdf);

        }



        PdfString.PdfStringComparer comparerType = PdfString.GetComparer();



        if (positionRect.Equals(PositionRect.Y2) || positionRect.Equals(PositionRect.Y1))

            comparerType.WhichComparison = PdfString.PdfStringComparer.ComparisonType.Horizontal;

        else if (positionRect.Equals(PositionRect.X1) || positionRect.Equals(PositionRect.X2))

            comparerType.WhichComparison = PdfString.PdfStringComparer.ComparisonType.Vertical;



        pdfStringFilter.Sort(comparerType);



        return pdfStringFilter;

    }



    private double GetRange(Rect pdf, Rect title, PositionRect positionRect)

    {

        switch (positionRect)

        {

            case PositionRect.X1:

                return Math.Abs(pdf.x1 - title.x1);

            case PositionRect.X2:

                return Math.Abs(pdf.x2 - title.x2);

            case PositionRect.Y1:

                return Math.Abs(pdf.y1 - title.y1);

            case PositionRect.Y2:

                return Math.Abs(pdf.y2 - title.y2);

            default:

                throw new Exception("calculation range of pdfstring with title error.");

        }

    }



    public List<PdfString> RegexExtractByPositionWithAllPage(PDFDoc doc, string pattern, Rect rect, PositionRect positionRect = PositionRect.Y2, double range = 2.0)

    {

        return GetNearbyPdfString(RegexSearchAllPages(doc, pattern), rect, positionRect, range);

    }



    public List<PdfString> RegexExtractByPositionWithRangePage(PDFDoc doc, string pattern, int startPage, int endPage, Rect rect, PositionRect positionRect = PositionRect.Y2, double range = 2.0)

    {

        return GetNearbyPdfString(RegexSearchByPageRange(doc, pattern, startPage, endPage), rect, positionRect, range);

    }

}

 
コメント:
1.RegexSearchAllPages、RegexSearchByPageRange、RegexSearchByPageメソッド名から、正規表現で検索されたPdfString結果の集合が分かる.
2.R e g e x ExtractByPositionWithPage、R e g e x ExtractByPositionWithAllPage、R e g e x ExtractByPositionWithRangePageは、メソッド名によって、入力座標と誤差範囲、または各行または各列のソート後のデータの集合のみが知られる.