【初心者向け】基礎&実践プログラミング

初心者がつまづきやすいところ、最短で実力が身につく方法をお伝えします。

【Python】スクレイピングで使うテキスト処理

目的

  • スクレイピングでよく使うテキスト処理を取得

はじめに

最近、戦友がねこちゃんを飼いました☆
しっぽが鍵(key(キー))みたいだから「きぃくん」と呼ぶそうです。
とっても可愛いので毎日みています!
よかったらインスタグラムフォローおねがいします!
https://www.instagram.com/keykun_0501/

また、ここで扱ったソースコードはGitHubにあげてありますのでもしよろしければお使いください。

github.com

スクレイピング

まずはじめに、インスタグラムからきぃくんのアカウントにアクセスします。

事前に許可はとってあります!

f:id:AIProgrammer:20200808192253p:plain

画像を保存するために、右クリックを押してみても「名前をつけて画像を保存する」という項目が出てきません。なので、通常の方法ではインスタグラムから画像を保存することができません。

f:id:AIProgrammer:20200808201208p:plain

そこで、私が開発した「Instagram Scraper」というアプリを使ってきぃくんのアカウントからすべての投稿を自動的に取得します。

f:id:AIProgrammer:20200808200102p:plain

取得した結果がこちらです。

  • 投稿画像 (.jpg)
  • 投稿動画 (.mp4)
  • 投稿情報 [投稿日、投稿コメント等] (.json)

f:id:AIProgrammer:20200808192043p:plain

画像をタイル状に並べてみましょう。 タイル状に並べる方法は、「【画像連結】画像をタイル状に並べる」をご覧ください。

$ ls *jpg
109070249_639378493598372_5791442249249671537_n.jpg
109718665_160293375563304_1259808192699931872_n.jpg
109807232_302400540814369_4247775928265355385_n.jpg
109874240_633604980695279_989044714179805495_n.jpg
110054171_577270736271788_5686323120543971116_n.jpg
110223942_2726628854324704_6150071321007915519_n.jpg
110303226_725669144932001_289648011926803037_n.jpg
111029410_762203397944994_2678400731143503175_n.jpg
114437063_902167146933871_2953874676373738180_n.jpg
115881452_924787774691986_3643587325937818477_n.jpg
115888313_2736287660030176_7175637167136915383_n.jpg
115992769_155623509531490_5576453553182753393_n.jpg
116156564_893786197787948_5868567380038261274_n.jpg
116234602_290285422063484_3568254065946470771_n.jpg
116572894_339522593737245_9125991746562514963_n.jpg
116583654_788646875305690_4890041376633210709_n.jpg

$ montage *jpg -geometry 256x256 -tile 4x4 tile.jpg

あら、かわいい! タイルにすると4x4倍かわいいですね〜。って、一枚変な画像が...

tile.jpg

f:id:AIProgrammer:20200808192858j:plain

ちなみに、投稿情報「keykun_0501.json」の中身はこのようになっています。

$ cat keykun_0501.json {
    "GraphImages": [
        {
            "__typename": "GraphImage",
            "comments": {
                "data": []
            },
            "comments_disabled": false,
            "dimensions": {
                "height": 1350,
                "width": 1080
            },
            "display_url": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/p1080x1080/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=152b9f24df0db398c695934226c59741&oe=5F57F6A7&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2",
            "edge_media_preview_like": {
                "count": 25
            },
            "edge_media_to_caption": {
                "edges": [
                    {
                        "node": {
                            "text": "本日のお昼寝\n\n#うちのねこ \n#ねこすきさんと繋かりたい\n#ねことの暮らし \n#ねこすたくらむ \n#ねこのいる生活 \n#ねこ写真 \n#ねこ\n#ねこ動画"
                        }
                    }
                ]
            },
            "edge_media_to_comment": {
                "count": 0
            },
            "gating_info": null,
            "id": "2367448883478332257",
            "is_video": false,
            "media_preview": "ACEq6AimM6ryxA+pp7MFBJ6CsOZzO+GbavrjOB270mM1ftEW4IHUs3QZ5NS1mW9oICSxDt2IGCB/Sr4Y55z+OCPzqbgPxRS0UAV78kQkjtg/rXPRXEavibJX0HXPqf8AOB2rqmAYEHkHgj2rnTphE21ziMnIbuR6expsC3bTvIoEfByMs2OVHYKOmenJrVGcc9aq7oYSI02hj1A6j6n9AKtipQxaKSimIWmsoYYNOpKYFQ2yg5wM1ZWlNN71NrbDH0UtFMR//9k=",
            "owner": {
                "id": "4182260661"
            },
            "shortcode": "CDa3jdbnwNh",
            "tags": [
                "ねこ動画",
                "ねことの暮らし",
                "ねこ写真",
                "ねこすきさんと繋か",
                "ねこのいる生活",
                "ねこ",
                "うちのねこ",
                "ねこすたく"
            ],
            "taken_at_timestamp": 1596441921,
            "thumbnail_resources": [
                {
                    "config_height": 150,
                    "config_width": 150,
                    "src": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s150x150/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=66a0f65724b6daa44362f578114db947&oe=5F570E33&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c"
                },
                {
                    "config_height": 240,
                    "config_width": 240,
                    "src": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s240x240/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d64d8c6c1d28425731cf0d5dfd0d5efa&oe=5F575135&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c"
                },
                {
                    "config_height": 320,
                    "config_width": 320,
                    "src": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s320x320/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=42b42768a58e7538ea9a78a4d1b8be8e&oe=5F5723CB&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c"
                },
                {
                    "config_height": 480,
                    "config_width": 480,
                    "src": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s480x480/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d9b2d87a43c8d91c89d7f583f18fc5d0&oe=5F57328E&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c"
                },
                {
                    "config_height": 640,
                    "config_width": 640,
                    "src": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/sh0.08/e35/c0.180.1440.1440a/s640x640/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d9f847829d305cd917f30334a8a13aaf&oe=5F587B03&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c"
                }
            ],
            "thumbnail_src": "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/sh0.08/e35/c0.180.1440.1440a/s640x640/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d9f847829d305cd917f30334a8a13aaf&oe=5F587B03&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c",
            "urls": [
                "https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/p1080x1080/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=152b9f24df0db398c695934226c59741&oe=5F57F6A7&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2"
            ],

...
[省略]

}

JSONファイルからテキストを読み込み

では、Pythonを使って「keykun_0501.json」から「投稿日」、「投稿コメント」を取得していきます。取得した情報は、Dict型になっています。

In:

import json

username = 'keykun_0501'

# load json file
with open('{}/{}.json'.format(username, username)) as f:
    jsn = json.load(f)

print(jsn)

Out:

{'GraphImages': [{'__typename': 'GraphImage', 'comments': {'data': []}, 'comments_disabled': False, 'dimensions': {'height': 1350, 'width': 1080}, 'display_url': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/p1080x1080/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=152b9f24df0db398c695934226c59741&oe=5F57F6A7&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2', 'edge_media_preview_like': {'count': 25}, 'edge_media_to_caption': {'edges': [{'node': {'text': '本日のお昼寝\n\n#うちのねこ \n#ねこすきさんと繋がりたい\n#ねことの暮らし \n#ねこすたぐらむ \n#ねこのいる生活 \n#ねこ写真 \n#ねこ\n#ねこ動画'}}]}, 'edge_media_to_comment': {'count': 0}, 'gating_info': None, 'id': '2367448883478332257', 'is_video': False, 'media_preview': 'ACEq6AimM6ryxA+pp7MFBJ6CsOZzO+GbavrjOB270mM1ftEW4IHUs3QZ5NS1mW9oICSxDt2IGCB/Sr4Y55z+OCPzqbgPxRS0UAV78kQkjtg/rXPRXEavibJX0HXPqf8AOB2rqmAYEHkHgj2rnTphE21ziMnIbuR6expsC3bTvIoEfByMs2OVHYKOmenJrVGcc9aq7oYSI02hj1A6j6n9AKtipQxaKSimIWmsoYYNOpKYFQ2yg5wM1ZWlNN71NrbDH0UtFMR//9k=', 'owner': {'id': '4182260661'}, 'shortcode': 'CDa3jdbnwNh', 'tags': ['ねこ動画', 'ねことの暮らし', 'ねこ写真', 'ねこすきさんと繋か', 'ねこのいる生活', 'ねこ', 'うちのねこ', 'ねこすたく'], 'taken_at_timestamp': 1596441921, 'thumbnail_resources': [{'config_height': 150, 'config_width': 150, 'src': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s150x150/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=66a0f65724b6daa44362f578114db947&oe=5F570E33&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c'}, {'config_height': 240, 'config_width': 240, 'src': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s240x240/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d64d8c6c1d28425731cf0d5dfd0d5efa&oe=5F575135&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c'}, {'config_height': 320, 'config_width': 320, 'src': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s320x320/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=42b42768a58e7538ea9a78a4d1b8be8e&oe=5F5723CB&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c'}, {'config_height': 480, 'config_width': 480, 'src': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/c0.180.1440.1440a/s480x480/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d9b2d87a43c8d91c89d7f583f18fc5d0&oe=5F57328E&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c'}, {'config_height': 640, 'config_width': 640, 'src': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/sh0.08/e35/c0.180.1440.1440a/s640x640/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d9f847829d305cd917f30334a8a13aaf&oe=5F587B03&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c'}], 'thumbnail_src': 'https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/sh0.08/e35/c0.180.1440.1440a/s640x640/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=d9f847829d305cd917f30334a8a13aaf&oe=5F587B03&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2.c', 'urls': ['https://scontent-nrt1-1.cdninstagram.com/v/t51.2885-15/e35/p1080x1080/116583654_788646875305690_4890041376633210709_n.jpg?_nc_ht=scontent-nrt1-1.cdninstagram.com&_nc_cat=110&_nc_ohc=2x8UMH0eu4IAX9J8nmh&oh=152b9f24df0db398c695934226c59741&oe=5F57F6A7&ig_cache_key=MjM2NzQ0ODg4MzQ3ODMzMjI1Nw%3D%3D.2'],

...
[省略]

取得したテキストの確認

JSONファイルから取得した情報を確認します。

まず、投稿数を確認します。

In:

# 投稿数
len(jsn['GraphImages'])

Out:

16

次に、要素を確認します。この内、投稿日は「taken_at_timestamp」、投稿コメントは「edge_media_to_caption」です。

In:

# 要素名
jsn['GraphImages'][15].keys()

Out:

dict_keys(['__typename', 'comments', 'comments_disabled', 'dimensions', 'display_url', 'edge_media_preview_like', 'edge_media_to_caption', 'edge_media_to_comment', 'gating_info', 'id', 'is_video', 'media_preview', 'owner', 'shortcode', 'tags', 'taken_at_timestamp', 'thumbnail_resources', 'thumbnail_src', 'urls', 'username'])

投稿日の取得

投稿日を取得します。ここでは、例として最初の投稿日を取得しています。(jsn['GraphImages']の16個目の配列)

この時取得した時間はUNIX時間(timestamp)になっています。

In:

# 最初の投稿日(UNIX時間)
timestamp = jsn['GraphImages'][15]['taken_at_timestamp']
print(timestamp)

Out:

1595378239

timestampからdatetimeに変換します。

In:

# 投稿日(UNIX時間)をdatetimeに変換
from datetime import datetime
date = datetime.fromtimestamp(timestamp)
print(date)

Out:

2020-07-22 09:37:19

投稿コメントの取得

ついに、投稿コメントを取得していきます。ここでは、最初の投稿コメントを取得しています。(jsn['GraphImages']の16個目の配列)

In:

# 最初の投稿コメント
caption = jsn['GraphImages'][15]['edge_media_to_caption']['edges'][0]['node']['text']
caption

Out:

'うちに猫が来た\n初日からこの寝相で真横で寝てくる懐っこい子笑\n\n#うちのねこ \n#ねこすきさんと繋がりたい\n#ねことの暮らし \n#ねこすたぐらむ \n#ねこのいる生活 \n#ねこ写真 \n#ねこ'

改行コード(\n)をスペースに置き換えることで改行コードを削除します。

In:

# 投稿コメントから改行コード(\n)を削除
caption_modified = caption.replace('\n',' ')
caption_modified

Out:

'うちに猫が来た 初日からこの寝相で真横で寝てくる懐っこい子笑  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ねこすたぐらむ  #ねこのいる生活  #ねこ写真  #ねこ'

すべての投稿日と投稿コメントを取得

以上を踏まえてきぃくんのアカウントのすべての投稿日と投稿コメントを取得し、CSVファイルにまとめて保存します。

In:

all_caption, all_date = [], []
for i in range(len(jsn['GraphImages'])):
    # 投稿日
    timestamp = jsn['GraphImages'][i]['taken_at_timestamp']
    date = datetime.fromtimestamp(timestamp)
    all_date.append(date)
    
    # 投稿コメント
    caption = jsn['GraphImages'][i]['edge_media_to_caption']['edges'][0]['node']['text']
    caption_modified = caption.replace('\n',' ')
    all_caption.append(caption_modified)

# 結果を表にまとめる
import pandas as pd
df = pd.DataFrame({'date':all_date,
                  'caption':all_caption})

# 結果をCSVファイルに保存
df.to_csv('{}/captions.csv'.format(username), index=False)

# 結果の確認
print(df)

Out:

                  date                                            caption
0  2020-08-03 17:05:21  本日のお昼寝  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ねこすた...
1  2020-08-01 09:23:14  本日のお昼寝  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ねこすた...
2  2020-07-30 10:09:08  きいくん、早朝に何度か透明の嘔吐をしました。 大丈夫かな、、、😭 経験のある方、教えてくださ...
3  2020-07-28 11:44:30  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ねこすたぐらむ  #ね...
4  2020-07-27 13:26:02  今日のひるね  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ねこすた...
5  2020-07-26 10:23:52  きまってる笑 天気いいな〜🐈  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮ら...
6  2020-07-25 21:18:35  ねてらっしゃいます動画ver  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮ら...
7  2020-07-24 21:17:35  おこられて隠れるきい 頭隠してなんとかかんとか🐈  #うちのねこ  #ねこすきさんと繋がり...
8  2020-07-24 20:31:04  折りたたみ式きいちゃん🐈  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし ...
9  2020-07-24 07:22:23  😋  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ねこすたぐらむ ...
10 2020-07-23 15:20:46  ねてらっしゃいますpart3  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮ら...
11 2020-07-22 20:36:16  ねてらっしゃいますpart2  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮ら...
12 2020-07-22 20:35:03  ねてらっしゃいます  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ね...
13 2020-07-22 20:06:04  鍵しっぽなので、きい。 ハイキュー観てる  #うちのねこ  #ねこすきさんと繋がりたい...
14 2020-07-22 19:58:56  あし1本だけうし。  #うちのねこ  #ねこすきさんと繋がりたい #ねことの暮らし  #ね...
15 2020-07-22 09:37:19  うちに猫が来た 初日からこの寝相で真横で寝てくる懐っこい子笑  #うちのねこ  #ねこ...

これからも、きぃくんのデータを題材とした処理・解析を取り上げていきますので楽しみにしていてください!



頑張れ!喝!!の代わりにB!ブックマークを押していただけるとただただうれしいです(^^)! ↓