Pythonでファイルから文字列を抽出する

## はじめに

**この記事で説明すること**
以下の機能のサンプルコード。

- 指定したディレクトリ配下のファイルの一覧を作成する
- ファイル内のテキストに特定の文字列が含まれるかどうかを調べる
- ファイル内のテキストから特定の文字列で囲まれた範囲のテキストを抽出する


**開発環境**

- python 2.7以上



## 指定したディレクトリ配下のファイルの一覧を作成する

#### コード

```python
def generate_file_list(dirpath_to_search):
    file_list = []
    for dirpath, dirnames, filenames in os.walk(dirpath_to_search):
        for filename in filenames:
             file_list.append(os.path.join(dirpath,filename))

    return file_list
```



#### 使用方法
以下のようなディレクトリ構成となっていて、sample1配下のファイル名を再帰的に取得したい場合のサンプル。

```txt:サンプルのディレクトリ構成
sample1/
├── dir01
│   ├── dir11
│   │   └── file21.txt
│   └── file11.txt
├── file01.txt
└── file02.txt
```

```python:使用方法
file_list = generate_file_list('sample1')
for file in file_list:
    print(file)

# 出力
# sample1/file01.txt
# sample1/file02.txt
# sample1/dir01/file11.txt
# sample1/dir01/dir11/file21.txt
```



#### 使用したAPI

[os.walk(top, topdown=True, onerror=None, followlinks=False)](https://docs.python.org/ja/3/library/os.html#os.walk)
> ディレクトリツリー以下のファイル名を、ツリーをトップダウンもしくはボトムアップに走査することで作成します。ディレクトリ top を根に持つディレクトリツリーに含まれる、各ディレクトリ (top 自身を含む ) ごとに、タプル (dirpath, dirnames, filenames) を yield します。


## ファイル内のテキストに特定の文字列が含まれるかどうかを調べる

#### コード

```python
def contain_text_in_file(filepath, text):
    with open(filepath) as f:
        return any(text in line for line in f)
```



#### 使用方法
以下のように`contain.txt`と`not_contain.txt`というファイルがあって、「2020/02/02」をファイル内に含むファイルを知りたい場合のサンプル。

```txt:contain.txt
更新日: 2020/02/02
この記事はpythonのファイル操作に関する記事です。
```

```txt:not_contain.txt
更新日: 2019/10/15
この記事はpythonのファイル操作に関する記事です。
```



```python:使用方法
filepath1 = './contain.txt'
text = '2020/02/02'
result1 = contain_text_in_file(filepath1, text)
print(result1) # True

filepath2 = './not_contain.txt'
text = '2020/02/02'
result2 = contain_text_in_file(filepath2, text)
print(result2) # False
```



#### 使用したAPI

[open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)](https://docs.python.org/ja/3/library/functions.html#open)
> file を開き、対応する ファイルオブジェクト を返します。

[any(iterable)](https://docs.python.org/ja/3/library/functions.html#any)
> iterable のいずれかの要素が真ならば True を返します。iterable が空なら False を返します。以下のコードと等価です:


## ファイル内のテキストから特定の文字列で囲まれた範囲のテキストを抽出する

#### コード

```python
import re

def extract_text_in_file(filepath, pattern_prev, pattern_next):
    extracted_text_array = []
    pattern = pattern_prev + '(.*)' + pattern_next
    with open(filepath) as f:
        lines = f.readlines()
        for line in lines:
            tmp_extracted_text_array = re.findall(pattern, line)
            extracted_text_array.extend(tmp_extracted_text_array)

    return extracted_text_array
```



#### 使用方法
以下のような`file.txt`というファイルがあって、「更新日」と「 by」に囲まれた日付部分を抽出したい場合のサンプル。

```txt:file.txt
更新日:2020/02/01 by taro
この記事はpythonのファイル操作に関する記事です。

更新日:2020/02/02 by jiro
この記事はpythonのファイル操作に関する記事です。
```



```python:使用方法
filepath = './file.txt'
pattern_prev = '更新日:'
pattern_next = ' by'
extracted_text_array = extract_text_in_file(filepath, pattern_prev, pattern_next)

for extracted_text in extracted_text_array:
    print(extracted_text)

# 出力
# 2020/02/01
# 2020/02/02
```



#### 使用したAPI

[re.findall(pattern, string, flags=0)](https://docs.python.org/ja/3/library/re.html#re.findall)
> string 中の pattern による全ての重複しないマッチを、文字列のリストとして返します。 string は左から右へ走査され、マッチは見つかった順で返されます。パターン中に 1 つ以上のグループがあれば、グループのリストを返します。パターンに複数のグループがあればタプルのリストになります。空マッチは結果に含まれます。

[open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)](https://docs.python.org/ja/3/library/functions.html#open)
> file を開き、対応する ファイルオブジェクト を返します。