[{"data":1,"prerenderedAt":556},["ShallowReactive",2],{"blog-list":3},[4],{"id":5,"title":6,"body":7,"date":544,"description":545,"extension":546,"image":24,"meta":547,"navigation":70,"path":548,"seo":549,"stem":550,"tags":551,"__hash__":555},"posts/posts/250204-oecu-instagram-embed.md","Instagramの埋め込みを作ったお話",{"type":8,"value":9,"toc":542},"minimark",[10,25,36,45,48,84,87,178,184,194,197,435,438,529,535,538],[11,12,13,14,17,18,20],"p",{},"こんにちは、大阪電気通信大学で学生広報スタッフをしていますYoshimasaです。",[15,16],"br",{},"\n今回以下のようなInstagramの埋め込みを表示するシステムを開発したので軽く技術的な面で書いてみようと思います。",[15,19],{},[21,22],"img",{"alt":23,"src":24,"title":23},"Instagram 埋め込み表示","/images/posts/250204-1.png",[11,26,27,28,30,31,35],{},"今回はライブラリが豊富なPythonを使って楽をしてプログラムを作りました。",[15,29],{},"\n利用しているライブラリとしては、",[32,33,34],"code",{},"instagrapi","というPythonライブラリです。これは、InstagramのAPIを簡単に扱うことが出来るライブラリです。",[11,37,38,39,41,42,44],{},"また、このライブラリを選んだ理由としてInstagramのログインをせずにユーザーの画像を取得することが出来た点が大きいです。",[15,40],{},"\n私が最初にInstagramからデータを取得しようとした際にログインを必要とするライブラリを利用していました。",[15,43],{},"\n最初はそれでも十分取得できたのですが、少しするとInstagramのアカウントが凍結されました。",[11,46,47],{},"そのため、回避をするためにログイン不要でかつ簡単にInstagramのデータを取得することが出来るinstagrapiを見つけたためこれを利用しています。",[49,50,55],"pre",{"className":51,"code":52,"language":53,"meta":54,"style":54},"language-python shiki shiki-themes github-light github-dark","from instagrapi import Client\n\ncl = Client()\nposts = cl.user_medias(\"InstagramのユーザーID\", 30)\n","python","",[32,56,57,65,72,78],{"__ignoreMap":54},[58,59,62],"span",{"class":60,"line":61},"line",1,[58,63,64],{},"from instagrapi import Client\n",[58,66,68],{"class":60,"line":67},2,[58,69,71],{"emptyLinePlaceholder":70},true,"\n",[58,73,75],{"class":60,"line":74},3,[58,76,77],{},"cl = Client()\n",[58,79,81],{"class":60,"line":80},4,[58,82,83],{},"posts = cl.user_medias(\"InstagramのユーザーID\", 30)\n",[11,85,86],{},"サイトにPythonで処理したデータを表示するために、JSON形式にPythonで一度再形成しています。",[49,88,90],{"className":51,"code":89,"language":53,"meta":54,"style":54},"postsArray = []\nfor post in posts:\n    thumbnail_url = \"\"\n    if post.thumbnail_url != None:\n        thumbnail_url = str(post.thumbnail_url)\n    else:\n        thumbnail_url = str(post.resources[0].thumbnail_url)\n    postData = {\n        \"date\": post.taken_at.isoformat(),\n        \"caption\": post.caption_text,\n        \"likes\": post.like_count,\n        \"thumbnail\": thumbnail_url,\n        \"id\": post.code,\n    }\n    postsArray.append(postData)\n",[32,91,92,97,102,107,112,118,124,130,136,142,148,154,160,166,172],{"__ignoreMap":54},[58,93,94],{"class":60,"line":61},[58,95,96],{},"postsArray = []\n",[58,98,99],{"class":60,"line":67},[58,100,101],{},"for post in posts:\n",[58,103,104],{"class":60,"line":74},[58,105,106],{},"    thumbnail_url = \"\"\n",[58,108,109],{"class":60,"line":80},[58,110,111],{},"    if post.thumbnail_url != None:\n",[58,113,115],{"class":60,"line":114},5,[58,116,117],{},"        thumbnail_url = str(post.thumbnail_url)\n",[58,119,121],{"class":60,"line":120},6,[58,122,123],{},"    else:\n",[58,125,127],{"class":60,"line":126},7,[58,128,129],{},"        thumbnail_url = str(post.resources[0].thumbnail_url)\n",[58,131,133],{"class":60,"line":132},8,[58,134,135],{},"    postData = {\n",[58,137,139],{"class":60,"line":138},9,[58,140,141],{},"        \"date\": post.taken_at.isoformat(),\n",[58,143,145],{"class":60,"line":144},10,[58,146,147],{},"        \"caption\": post.caption_text,\n",[58,149,151],{"class":60,"line":150},11,[58,152,153],{},"        \"likes\": post.like_count,\n",[58,155,157],{"class":60,"line":156},12,[58,158,159],{},"        \"thumbnail\": thumbnail_url,\n",[58,161,163],{"class":60,"line":162},13,[58,164,165],{},"        \"id\": post.code,\n",[58,167,169],{"class":60,"line":168},14,[58,170,171],{},"    }\n",[58,173,175],{"class":60,"line":174},15,[58,176,177],{},"    postsArray.append(postData)\n",[11,179,180,181,183],{},"また、Instagramの画像に関しても一度S3ドライブに保存してその画像を読み込むようにしています。",[15,182],{},"\n※ Instagramの画像がCORSでうまく表示できなかったため。",[11,185,186,187,190,191,193],{},"PythonでS3にデータを保存するには、",[32,188,189],{},"boto","というPythonライブラリを利用します。",[15,192],{},"\nこの説明は割愛します。（ググったら沢山情報出てくるはずです。）",[11,195,196],{},"最終的に出来るJSONデータは以下のようなデータになります。",[49,198,202],{"className":199,"code":200,"language":201,"meta":54,"style":54},"language-json shiki shiki-themes github-light github-dark","{\n  \"updated_at\": 1738656014,\n  \"latest_posts\": [\n    {\n      \"date\": \"2025-02-04T04:35:52+00:00\",\n      \"caption\": \"D専攻学生広報突撃インタビュー！\\n3回目は寶珍先生に突撃しました^ ^\\n\\n#大阪電気通信大学 #oecu #学生広報 #建築学科 #インタビュー #寝屋川\",\n      \"likes\": 1,\n      \"thumbnail\": \"Instagramの画像URL\",\n      \"id\": \"DFo0BdpyGCb\"\n    },\n    {\n      \"date\": \"2025-02-04T04:00:00+00:00\",\n      \"caption\": \"基礎理工学科の先生をリレー形式で取材！\\n第3回は、森田先生にインタビュー\\n\\nパートを分けてお届けします！今回はパート3！\\n\\n化学のおもしろいトコロ\\n\\n出演 : 森田先生, まな, れね\\n編集 : Yoshimasa\\n\\n #大阪電気通信大学 #学生広報 #寝屋川  #基礎理工学科  #リケジョ #インタビュー\",\n      \"likes\": 4,\n      \"thumbnail\": \"Instagramの画像URL\",\n      \"id\": \"DFov9kFSCM8\"\n    },\n    { \"省略\": \"\" }\n  ]\n}\n","json",[32,203,204,210,225,233,238,251,275,287,299,309,314,318,329,370,381,391,401,406,423,429],{"__ignoreMap":54},[58,205,206],{"class":60,"line":61},[58,207,209],{"class":208},"sVt8B","{\n",[58,211,212,216,219,222],{"class":60,"line":67},[58,213,215],{"class":214},"sj4cs","  \"updated_at\"",[58,217,218],{"class":208},": ",[58,220,221],{"class":214},"1738656014",[58,223,224],{"class":208},",\n",[58,226,227,230],{"class":60,"line":74},[58,228,229],{"class":214},"  \"latest_posts\"",[58,231,232],{"class":208},": [\n",[58,234,235],{"class":60,"line":80},[58,236,237],{"class":208},"    {\n",[58,239,240,243,245,249],{"class":60,"line":114},[58,241,242],{"class":214},"      \"date\"",[58,244,218],{"class":208},[58,246,248],{"class":247},"sZZnC","\"2025-02-04T04:35:52+00:00\"",[58,250,224],{"class":208},[58,252,253,256,258,261,264,267,270,273],{"class":60,"line":120},[58,254,255],{"class":214},"      \"caption\"",[58,257,218],{"class":208},[58,259,260],{"class":247},"\"D専攻学生広報突撃インタビュー！",[58,262,263],{"class":214},"\\n",[58,265,266],{"class":247},"3回目は寶珍先生に突撃しました^ ^",[58,268,269],{"class":214},"\\n\\n",[58,271,272],{"class":247},"#大阪電気通信大学 #oecu #学生広報 #建築学科 #インタビュー #寝屋川\"",[58,274,224],{"class":208},[58,276,277,280,282,285],{"class":60,"line":126},[58,278,279],{"class":214},"      \"likes\"",[58,281,218],{"class":208},[58,283,284],{"class":214},"1",[58,286,224],{"class":208},[58,288,289,292,294,297],{"class":60,"line":132},[58,290,291],{"class":214},"      \"thumbnail\"",[58,293,218],{"class":208},[58,295,296],{"class":247},"\"Instagramの画像URL\"",[58,298,224],{"class":208},[58,300,301,304,306],{"class":60,"line":138},[58,302,303],{"class":214},"      \"id\"",[58,305,218],{"class":208},[58,307,308],{"class":247},"\"DFo0BdpyGCb\"\n",[58,310,311],{"class":60,"line":144},[58,312,313],{"class":208},"    },\n",[58,315,316],{"class":60,"line":150},[58,317,237],{"class":208},[58,319,320,322,324,327],{"class":60,"line":156},[58,321,242],{"class":214},[58,323,218],{"class":208},[58,325,326],{"class":247},"\"2025-02-04T04:00:00+00:00\"",[58,328,224],{"class":208},[58,330,331,333,335,338,340,343,345,348,350,353,355,358,360,363,365,368],{"class":60,"line":162},[58,332,255],{"class":214},[58,334,218],{"class":208},[58,336,337],{"class":247},"\"基礎理工学科の先生をリレー形式で取材！",[58,339,263],{"class":214},[58,341,342],{"class":247},"第3回は、森田先生にインタビュー",[58,344,269],{"class":214},[58,346,347],{"class":247},"パートを分けてお届けします！今回はパート3！",[58,349,269],{"class":214},[58,351,352],{"class":247},"化学のおもしろいトコロ",[58,354,269],{"class":214},[58,356,357],{"class":247},"出演 : 森田先生, まな, れね",[58,359,263],{"class":214},[58,361,362],{"class":247},"編集 : Yoshimasa",[58,364,269],{"class":214},[58,366,367],{"class":247}," #大阪電気通信大学 #学生広報 #寝屋川  #基礎理工学科  #リケジョ #インタビュー\"",[58,369,224],{"class":208},[58,371,372,374,376,379],{"class":60,"line":168},[58,373,279],{"class":214},[58,375,218],{"class":208},[58,377,378],{"class":214},"4",[58,380,224],{"class":208},[58,382,383,385,387,389],{"class":60,"line":174},[58,384,291],{"class":214},[58,386,218],{"class":208},[58,388,296],{"class":247},[58,390,224],{"class":208},[58,392,394,396,398],{"class":60,"line":393},16,[58,395,303],{"class":214},[58,397,218],{"class":208},[58,399,400],{"class":247},"\"DFov9kFSCM8\"\n",[58,402,404],{"class":60,"line":403},17,[58,405,313],{"class":208},[58,407,409,412,415,417,420],{"class":60,"line":408},18,[58,410,411],{"class":208},"    { ",[58,413,414],{"class":214},"\"省略\"",[58,416,218],{"class":208},[58,418,419],{"class":247},"\"\"",[58,421,422],{"class":208}," }\n",[58,424,426],{"class":60,"line":425},19,[58,427,428],{"class":208},"  ]\n",[58,430,432],{"class":60,"line":431},20,[58,433,434],{"class":208},"}\n",[11,436,437],{},"そして、JavaScriptで以下のようなコードで表示させています。",[49,439,443],{"className":440,"code":441,"language":442,"meta":54,"style":54},"language-javascript shiki shiki-themes github-light github-dark","let listElm = document.getElementById(\"ysms_instagram_list\");\nlet getData = await fetch(\"https://files-oecu.ysms.dev/instagram_oecu_kouhou/data.json\");\nlet dataJson = await getData.json();\nfor (const postKey in dataJson.latest_posts) {\n  if (postKey > 8) continue;\n  let post = dataJson.latest_posts[postKey];\n  listElm.innerHTML += `\n      \u003Ca rel=\"nofollow\" href=\"https://instagram.com/p/${post.id}/\" target=\"_blank\">\n          \u003Cimg src=\"https://files-oecu.ysms.dev/instagram_oecu_kouhou/${post.id}.jpg\" loading=\"auto\" alt=\"${post.caption.substring(0, 20)}...\" width=\"100%\">\n          \u003Cdiv class=\"ysms_instagram_info\">\n            \u003Cdiv class=\"img-caption\">\n                    ${post.caption.substring(0, 50)}...\n            \u003C/div>\n        \u003C/div>\n      \u003C/a>\n    `;\n}\n","javascript",[32,444,445,450,455,460,465,470,475,480,485,490,495,500,505,510,515,520,525],{"__ignoreMap":54},[58,446,447],{"class":60,"line":61},[58,448,449],{},"let listElm = document.getElementById(\"ysms_instagram_list\");\n",[58,451,452],{"class":60,"line":67},[58,453,454],{},"let getData = await fetch(\"https://files-oecu.ysms.dev/instagram_oecu_kouhou/data.json\");\n",[58,456,457],{"class":60,"line":74},[58,458,459],{},"let dataJson = await getData.json();\n",[58,461,462],{"class":60,"line":80},[58,463,464],{},"for (const postKey in dataJson.latest_posts) {\n",[58,466,467],{"class":60,"line":114},[58,468,469],{},"  if (postKey > 8) continue;\n",[58,471,472],{"class":60,"line":120},[58,473,474],{},"  let post = dataJson.latest_posts[postKey];\n",[58,476,477],{"class":60,"line":126},[58,478,479],{},"  listElm.innerHTML += `\n",[58,481,482],{"class":60,"line":132},[58,483,484],{},"      \u003Ca rel=\"nofollow\" href=\"https://instagram.com/p/${post.id}/\" target=\"_blank\">\n",[58,486,487],{"class":60,"line":138},[58,488,489],{},"          \u003Cimg src=\"https://files-oecu.ysms.dev/instagram_oecu_kouhou/${post.id}.jpg\" loading=\"auto\" alt=\"${post.caption.substring(0, 20)}...\" width=\"100%\">\n",[58,491,492],{"class":60,"line":144},[58,493,494],{},"          \u003Cdiv class=\"ysms_instagram_info\">\n",[58,496,497],{"class":60,"line":150},[58,498,499],{},"            \u003Cdiv class=\"img-caption\">\n",[58,501,502],{"class":60,"line":156},[58,503,504],{},"                    ${post.caption.substring(0, 50)}...\n",[58,506,507],{"class":60,"line":162},[58,508,509],{},"            \u003C/div>\n",[58,511,512],{"class":60,"line":168},[58,513,514],{},"        \u003C/div>\n",[58,516,517],{"class":60,"line":174},[58,518,519],{},"      \u003C/a>\n",[58,521,522],{"class":60,"line":393},[58,523,524],{},"    `;\n",[58,526,527],{"class":60,"line":403},[58,528,434],{},[11,530,531,532,534],{},"シンプルで簡単ですね。",[15,533],{},"\nこれ以上説明することないと思うので、後は困ったらChatGPTにでも聞いてみてください。",[11,536,537],{},"じゃあね！！",[539,540,541],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":54,"searchDepth":67,"depth":67,"links":543},[],"2025-02-04","InstagramのAPIとPythonを使って、ログイン不要で画像を埋め込むシステムを開発しました。","md",{},"/posts/250204-oecu-instagram-embed",{"title":6,"description":545},"posts/250204-oecu-instagram-embed",[552,553,554],"System","Python","Instagram","NYq2DKYoX2mEfl-5zrxRQGGUK4GfkM8E5oTJ6eN7RMc",1764654690620]