技術共有

PDF の指定された領域のコンテンツを Excel にバッチ抽出し、PDF ファイルのテキストの最初の行に基づいて v1.3 の名前を自動的に変更します - アイデアとコードの実装

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

この記事の更新内容では、写真とスキャンした PDF も指定領域のコンテンツのバッチ抽出をサポートできます。これは主に指定領域のスクリーンショットを撮り、OCR を使用して領域内のテキストを識別することで実現されるため、精度が低い場合があります。これで十分ですが、デジタルであれば大きな問題にはならないため、最大限の効果を得るには、純粋に電子バージョンの PDF ファイルを抽出するのが最善です。


要件 1: 同じ形式の PDF 電子ドキュメントが多数ある場合、特定の領域の数字またはテキストを抽出する必要があります。

要件 2: PDF ドキュメントのバッチがありますが、ファイル名がすべて文字化けしています。PDF ファイルの最初のページの最初の行のタイトル テキストに基づいて、これらのファイルの名前をバッチ変更する必要があります。

注: シナリオには適していません: 複数の PDF ファイルから抽出する必要がある領域の位置が異なる場合、たとえば、抽出したい番号が最初の PDF ファイルの (30, 30) の座標にある場合、 2 番目のファイルで結果が (35, 35) の座標になると、ソフトウェアはコンテンツのテキストをうまく抽出できなくなります。そのため、このコードの適用範囲は、複数の PDF ドキュメントが含まれることになります。同じ形式であり、抽出する必要があるテキスト情報が配置されている PDF の位置も基本的に同じです。

アイデア 1: PDF ファイルをサンプルとしてランダムに選択し、コードを使用して抽出する領域をボックスでマークし、これらの領域の座標を保存します。各 PDF をバッチで処理するときに、保存された地域座標を使用します。場所に対応するテキストまたは数字を抽出するには

アイデアの概略図:

最終的な結果図:

このアイデアの欠点と注意が必要な点は次のとおりです。

1 各バッチ処理ファイルから抽出するデータの位置は同じである必要があります。たとえば、最初の PDF ファイルから抽出する数値は座標 [100, 100] にあり、次に抽出する数値が配置されます。後続の各ファイルから抽出されるデータは、座標 [100, 100] に配置される必要があります。この位置が変更されると、必要なデータが抽出されなくなります。この問題は、領域の座標範囲を拡張することである程度解決できます。

2. 抽出されたテキストが不完全な場合は、選択したボックスが若干小さくなる可能性があることを意味します。コード内に特定の領域のサイズを個別に拡大する関数を設定しました。


要件 2 アイデア: PDF ドキュメントのバッチの名前がす​​べて文字化けしている場合、PDF ファイルの最初のページのタイトルに基づいてこれらのファイルの名前を変更する必要があります。実際、これは非常に簡単です。 PDF ファイルを作成し、PDF ファイルのコンテンツの最初の行を取得して、ファイルの名前を変更します。このコードは複雑ではないため、このページには含まれていません。

コード:

  1. from typing import Optional, Dict, List
  2. from solapi.magic_eden.site_api.utils.consts import MEAPIUrls
  3. from solapi.magic_eden.site_api.utils.data import collection_stats_cleaner, collection_info_cleaner,
  4. collection_list_stats_cleaner
  5. from solapi.magic_eden.site_api.utils.types import MECollectionStats, MECollectionInfo, MECollectionMetrics
  6. from solapi.utils.api import BaseApi
  7. class MagicEdenCollectionApi(BaseApi):
  8. def get_collection_stats_dirty(self, symbol: str) -> Optional[Dict]:
  9. url = f'{MEAPIUrls.COLLECTION_STATS}{symbol}'
  10. res = self._get_request(url)
  11. return res.get('results') if isinstance(res, dict) else None
  12. def get_collection_info_dirty(self, symbol: str) -> Optional[Dict]:
  13. url = f'{MEAPIUrls.COLLECTION_INFO}{symbol}'
  14. res = self._get_request(url)
  15. return res if bool(res) else None
  16. def get_collection_stats(self, symbol: str) -> Optional[MECollectionStats]:
  17. data = self.get_collection_stats_dirty(symbol)
  18. if data:
  19. return collection_stats_cleaner(data)
  20. def get_collection_info(self, symbol: str) -> Optional[MECollectionInfo]:
  21. data = self.get_collection_info_dirty(symbol)
  22. if data:
  23. return collection_info_cleaner(data)
  24. def get_collection_list_stats_dirty(self):
  25. url = MEAPIUrls.COLLECTION_LIST_STATS
  26. res = self._get_request(url)
  27. return res.get('results') if isinstance(res, dict) else None
  28. def get_collection_list_stats(self) -> Optional[List[MECollectionMetrics]]:
  29. data = self.get_collection_list_stats_dirty()
  30. if data:
  31. return list(map(lambda x: collection_list_stats_cleaner(x), data))
  32. def get_collection_list_dirty(self):
  33. url = MEAPIUrls.COLLECTION_LIST
  34. res = self._get_request(url)
  35. return res.get('collections') if isinstance(res, dict) else None
  36. def get_collection_list(self) -> Optional[List[MECollectionInfo]]:
  37. data = self.get_collection_list_dirty()
  38. if data:
  39. return list(map(lambda x: collection_info_cleaner(x), data))

コードのダウンロード リンク:

リンク: https://pan.baidu.com/s/1WQQ8kaDilaagjoK5IrYZzA

抽出コード:1111