4 ๋ถ„ ์†Œ์š”

instagrapi?

ํ˜„์žฌ ์ธ์Šคํƒ€๊ทธ๋žจ์—์„œ ์ œ๊ณตํ•˜๋Š” api๋Š” Instagram ๊ทธ๋ž˜ํ”„ API์™€ Instagram ๊ธฐ๋ณธ ๋””์Šคํ”Œ๋ ˆ์ด API๊ฐ€ ์กด์žฌํ•œ๋‹ค.

์ด ์ค‘, ์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ API์™€ Meta์— ์•ฑ๊ณผ ๊ณ„์ •์„ ๊ฒ€์ˆ˜ ๋ฐ ์ธ์ฆ๋ฐ›์€ ๋น„์ฆˆ๋‹ˆ์Šค ๋ฐ ํฌ๋ฆฌ์—์ดํ„ฐ ๊ณ„์ • API๋กœ ๋‚˜๋‰˜์–ด์ ธ์žˆ๋‹ค.

์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ API๋Š” Instagram ๊ธฐ๋ณธ ๋””์Šคํ”Œ๋ ˆ์ด API์ด๊ณ , ๋น„์ฆˆ๋‹ˆ์Šค ๋ฐ ํฌ๋ฆฌ์—์ด์–ด ๊ณ„์ •๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ API๋Š” Instagram ๊ทธ๋ž˜ํ”„ API์ด๋‹ค.

Instagram ๊ธฐ๋ณธ ๋””์Šคํ”Œ๋ ˆ์ด API๋กœ๋Š” ๊ฒŒ์‹œ๋ฌผ์˜ ์ •๋ณด์™€ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์ฝ์–ด์˜ค๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.
์ฆ‰, Instagram ๊ทธ๋ž˜ํ”„ API๋งŒ ์‚ฌ์šฉ์ž์˜ ๊ณ„์ •์— ๊ฒŒ์‹œ๋ฌผ์„ ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

Instagram ๊ทธ๋ž˜ํ”„ API = Instagram ๊ธฐ๋ณธ ๋””์Šคํ”Œ๋ ˆ์ด API + ๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ ๊ธฐ๋Šฅ ์ •๋„๋กœ ์•Œ๊ณ ์žˆ์œผ๋ฉด ๋ ๋“ฏ

์ด๋Ÿฐ ๋ถˆํŽธํ•จ์„ ํ•ด์†Œํ•˜๊ณ ์ž Python์„ ์‚ฌ์šฉํ•˜๋Š” ์„ธ๊ณ„ ์—ฌ๋Ÿฌ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ธ์Šคํƒ€๊ทธ๋žจ์— ๊ฒŒ์‹œ๋ฌผ์„ ์—…๋กœ๋“œ ๋ฐ ๋‹ค์šด๋กœ๋“œ์™€ ๊ฐ™์€ ๊ฐ์ข… ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋†“์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์กด์žฌํ•œ๋‹ค.
๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ instagrapi์ด๋‹ค.

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•ด๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • instagrapi
  • instabot

๊ทธ ์ค‘, instagrapi๊ฐ€ ๋” ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ณ , ์กฐ๊ธˆ ๋” ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์› ์–ด์„œ instagrapi์— ๋Œ€ํ•ด ์ž‘์„ฑํ•œ๋‹ค.
instagrapi ๊ณต์‹ docs
instagrapi๋Š” ์ธ์Šคํƒ€๊ทธ๋žจ์—์„œ ๊ณต์‹์ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์•„๋‹Œ ๋น„๊ณต์‹ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ˆ ์ฃผ์˜ํ•˜์ž. (๋ฒ„์ „ ํ˜ธํ™˜์— ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜๋„..)

instagrapi ์„ค์น˜

pip install instagrapi

์œ„ ๋ช…๋ น์–ด๋กœ ๋จผ์ € instagrapi๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด ๋ชจ๋“ˆ์„ import ํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด๋œ๋‹ค.

from instagrapi import Client

client = Client()

๊ทธ๋Ÿฌ๋ฉด ์‚ฌ์šฉํ•  ์ค€๋น„๋Š” ๋๋‚ฌ๋‹ค. ๊ฐœ๊ฟ€

๊ณ„์ • ๋กœ๊ทธ์ธ

from instagrapi import Client

client = Client()

client.login(username, password)
  • username: ์ธ์Šคํƒ€๊ทธ๋žจ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์šฉ์ž ์•„์ด๋”” - @hellojunho ์—์„œ @๋ฅผ ์ œ์™ธํ•œ ๋ถ€๋ถ„
  • password: ์ธ์Šคํƒ€๊ทธ๋žจ ๊ณ„์ •์˜ ๋น„๋ฐ€๋ฒˆํ˜ธ

๊ณ„์ • ๋กœ๊ทธ์•„์›ƒ

from instagrapi import Client

client = Client()

client.logout()

๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ

๊ฒŒ์‹œ๋ฌผ์—๋„ ์—ฌ๋Ÿฌ ๊ฒฝ์šฐ๊ฐ€ ์กด์žฌํ•œ๋‹ค.
์ด๋ฏธ์ง€ 1์žฅ, ์ด๋ฏธ์ง€ 2์žฅ ์ด์ƒ, ๋น„๋””์˜ค 1์žฅ, ๋น„๋””์˜ค 2์žฅ ์ด์ƒ, ์ด๋ฏธ์ง€ 1์žฅ + ๋น„๋””์˜ค 1์žฅ ๋“ฑโ€ฆ

๊ฐ ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

์ด๋ฏธ์ง€ 1์žฅ ์—…๋กœ๋“œ

from instagrapi import Client

client = Client()

client.login(username, password)

media_path = "/Users/hellojunho/instagrapi_test/image/media1.jpeg"
caption = "hellojunho์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์˜ˆ์ œ1"

client.photo_upload(media_path, caption)

์ด๋ฏธ์ง€๊ฐ€ 1์žฅ์ธ ๊ฒฝ์šฐ์—๋Š” photo_upload(media_path, caption)์„ ์‚ฌ์šฉํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

์ด๋ฏธ์ง€ 2์žฅ ์ด์ƒ ์—…๋กœ๋“œ

from instagrapi import Client

client = Client()

client.login(username, password)

media_path = ["/Users/hellojunho/instagrapi_test/image/media1.jpeg", ""/Users/hellojunho/instagrapi_test/image/media2.jpeg", ...]
caption = "hellojunho์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์˜ˆ์ œ2"

client.album_upload(media_path, caption)

์ด๋ฏธ์ง€๊ฐ€ 2์žฅ ์ด์ƒ์ธ ๊ฒฝ์šฐ์—๋Š” album_upload(media_path, caption)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€ media_path๊ฐ€ list ๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค๋Š” ์ ์ด๋‹ค.

๋น„๋””์˜ค 1๊ฐœ ์—…๋กœ๋“œ

from instagrapi import Client

client = Client()

client.login(username, password)

media_path = "/Users/hellojunho/instagrapi_test/video/media3.mp4"
caption = "hellojunho์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์˜ˆ์ œ3"

client.video_upload(media_path, caption)

๋น„๋””์˜ค์˜ ๊ฒฝ์šฐ์—๋Š” ์ด๋ฏธ์ง€ 1์žฅ๊ณผ ๋น„์Šทํ•˜๊ฒŒ media_path๊ฐ€ str์ด๊ณ , video_upload(media_path, caption)์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๋งŒ์•ฝ ๋น„๋””์˜ค ์—…๋กœ๋“œ์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ๋‹ค๋ฉด MacOS์˜ ๊ฒฝ์šฐ์—๋Š” brew install ffmpeg์„ ํ•ด๋ณด๊ธฐโ€ฆ

๋น„๋””์˜ค 2๊ฐœ ์ด์ƒ ์—…๋กœ๋“œ

from instagrapi import Client

client = Client()

client.login(username, password)

media_path = ["/Users/hellojunho/instagrapi_test/video/media3.mp4", "/Users/hellojunho/instagrapi_test/video/media4.mp4", ... ]
caption = "hellojunho์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์˜ˆ์ œ4"

client.album_upload(media_path, caption)

๋น„๋””์˜ค ์—ฌ๋Ÿฌ ๊ฐœ๋Š” video_upload() ๋Œ€์‹ ์— album_upload(media_path, caption)์„ ์‚ฌ์šฉํ•œ๋‹ค.

ํ˜ผํ•ฉ ๋ฏธ๋””์–ด (์‚ฌ์ง„ + ๋น„๋””์˜ค)

from instagrapi import Client

client = Client()

client.login(username, password)

media_path = ["/Users/hellojunho/instagrapi_test/image/media1.jpeg", "/Users/hellojunho/instagrapi_test/image/media2.jpeg", "/Users/hellojunho/instagrapi_test/video/media3.mp4", "/Users/hellojunho/instagrapi_test/video/media4.mp4", ... ]
caption = "hellojunho์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์˜ˆ์ œ5"

client.album_upload(media_path, caption)

ํ˜ผํ•ฉ ๋ฏธ๋””์–ด์˜ ๊ฒฝ์šฐ์—๋Š” album_upload(media_path, capion)์„ ์‚ฌ์šฉํ•œ๋‹ค.
์ด ๋•Œ, ์ฃผ์˜ํ•  ์ ์€ media_path๊ฐ€ list๋ผ๋Š” ์ ๊ณผ media_path์— ์ž…๋ ฅ๋œ ๋ฏธ๋””์–ด์˜ ์ˆœ์„œ๋Œ€๋กœ ๊ฒŒ์‹œ๋œ๋‹ค๋Š” ์ ์ด๋‹ค.
ํ˜„์žฌ ์˜ˆ์‹œ์—๋Š” [์ด๋ฏธ์ง€1, ์ด๋ฏธ์ง€2, ๋น„๋””์˜ค1, ๋น„๋””์˜ค2]์˜ ์ˆœ์œผ๋กœ ์ง€์ •๋˜์–ด์žˆ์œผ๋‹ˆ, ์ธ์Šคํƒ€๊ทธ๋žจ ๊ฒŒ์‹œ๋ฌผ์—๋„ ์ด ์ˆœ์„œ์™€ ๋™์ผํ•˜๊ฒŒ ์—…๋กœ๋“œ ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ

๋‚˜๋Š” instagrapi๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•˜๋Š” ๋ถ€๋ถ„์„ class๋กœ ์ •์˜ํ•˜๊ณ , ์‹คํ–‰ํ•  python ํŒŒ์ผ์—์„œ๋Š” ํ•จ์ˆ˜๋กœ ๊ตฌ๋ถ„ํ•ด์„œ ๋‹จ์œ„ ๊ธฐ๋Šฅ ๋ณ„๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค. ๋ชจ๋‘ ํ…Œ์ŠคํŠธ์— ์„ฑ๊ณตํ–ˆ๋‹ค.

insta_post.py

from instagrapi import Client
import os
from dotenv import load_dotenv
load_dotenv()

class InstaPost():
    
    def __init__(self) -> None:
        self.client = Client()
        self.isLogined = False

    def instaLogin(self, username, password):
        try:
            self.client.login(username, password)
            self.isLogined = True
            message = "๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค."
            print(message)
            return "๋กœ๊ทธ์ธ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค."
        
        except Exception as e:
            if "We couldn't find an account with the username" in str(e):
                print("์•„์ด๋”” ํ˜น์€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.")
            else:
                print("๋กœ๊ทธ์ธ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค:", e)
                
    def get_profile_image(self):
        if self.isLogined:
            profile_img = self.client.user_info_by_username(self.client.username).profile_pic_url
            return profile_img
                
    # ์ด๋ฏธ์ง€ ํ•œ ์žฅ ์—…๋กœ๋“œ            
    def image_upload_one(self, media_path, caption):
        if self.isLogined:
            try:
                self.client.photo_upload(media_path, caption)
                message = "๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ๋ฅผ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค."
                return message
            except Exception as e:
                print("๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ ์ค‘ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.", e)
        else:
            message = "๋กœ๊ทธ์ธ ๋จผ์ € ํ•ด์ฃผ์„ธ์š”."
            return message          
        
    # ๋น„๋””์˜ค ํ•œ ๊ฐœ ์—…๋กœ๋“œ
    def video_upload_one(self, media_path, caption):
        if self.isLogined:
            try:
                self.client.video_upload(media_path, caption)
                message = "๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ๋ฅผ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค."
                return message
            except Exception as e:
                print("๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ ์ค‘ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.", e)
        else:
            message = "๋กœ๊ทธ์ธ ๋จผ์ € ํ•ด์ฃผ์„ธ์š”."
            return message
        
    # ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฏธ๋””์–ด ์—…๋กœ๋“œ(์ด๋ฏธ์ง€ ์—ฌ๋Ÿฌ ์žฅ, ๋น„๋””์˜ค ์—ฌ๋Ÿฌ ๊ฐœ, ์‚ฌ์ง„ + ๋น„๋””์˜ค ๋“ฑ...)
    def album_upload(self, media_path, caption):
        if self.isLogined:
            try:
                self.client.album_upload(media_path, caption)
                message = "๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ๋ฅผ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค."
                return message
            except Exception as e:
                print("๊ฒŒ์‹œ๋ฌผ ์—…๋กœ๋“œ ์ค‘ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.", e)
        else:
            message = "๋กœ๊ทธ์ธ ๋จผ์ € ํ•ด์ฃผ์„ธ์š”."
            return message        


    # ๋ฏธ๋””์–ด ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์™€ ์ €์žฅ (media_path๊ฐ€ str์ธ ๊ฒฝ์šฐ)
    def save_media(self, media_path):
        folder_path = os.path.join(os.path.dirname(__file__), "", "media")
        media_name = os.path.basename(media_path)
        destination_path = os.path.join(folder_path, media_name)

        try:
            with open(media_path, "rb") as f_source:
                with open(destination_path, "wb") as f_dest:
                    f_dest.write(f_source.read())
            print(f"Media saved to: {destination_path}")
            return destination_path
        except Exception as e:
            print("Error saving media:", e)

            
    def save_media_by_list(self, media_path):
        folder_path = os.path.join(os.path.dirname(__file__), "media")
        
        try:
            for m_path in media_path:
                media_name = os.path.basename(m_path)
                destination_path = os.path.join(folder_path, media_name)
                
                with open(m_path, "rb") as f_source:
                    with open(destination_path, "wb") as f_dest:
                        f_dest.write(f_source.read())
                print(f"Media saved to: {destination_path}")
            return folder_path  # ์ €์žฅ๋œ ํด๋” ๊ฒฝ๋กœ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
        except Exception as e:
            print("Error saving media:", e)

insta_post_ex.py

from insta_post import InstaPost
from datetime import datetime
import os
from dotenv import load_dotenv
load_dotenv()

username = os.getenv("INSTAGRAM_USER_ID")
password = os.getenv("INSTAGRAM_USER_PASSWORD")
contents_path = os.getenv("CONTENTS_PATH")

client = InstaPost()
client.instaLogin(username, password)


def photo_upload():
    media_filename = "photo1.jpeg"
    media_path = contents_path + media_filename
    caption = f"ํ˜„์žฌ ์‹œ๊ฐ„: {datetime.now()}"

    if client.isLogined:
        try:
            saved_media_path = client.save_media(media_path)
        except Exception as e:
            print("์ด๋ฏธ์ง€ ์ €์žฅ ์‹คํŒจ", e)
    else:
        print("Login first.")
    client.image_upload_one(media_path, caption)


def video_upload():
    media_filename = "video1.mp4"
    media_path = contents_path + media_filename
    caption = f"{datetime.now()} upload test"

    if client.isLogined:
        try:
            saved_media_path = client.save_media(media_path)
        except Exception as e:
            print("์ด๋ฏธ์ง€ ์ €์žฅ ์‹คํŒจ", e)
    else:
        print("Login first.")

    client.video_upload_one(media_path, caption)


def album_upload():
    media_filename = ["video1.mp4", "video2.mp4", "photo1.jpeg", "photo2.jpeg"]
    prefix_path = contents_path
    media_path =  [prefix_path + i for i in media_filename]
    caption = f"ํ˜„์žฌ ์‹œ๊ฐ„: {datetime.now()}"
    # print(media_path)

    if client.isLogined:
        try:
            saved_media_path = client.save_media_by_list(media_path)
        except Exception as e:
            print("์ด๋ฏธ์ง€ ์ €์žฅ ์‹คํŒจ", e)
    else:
        print("Login first.")
    client.album_upload(media_path, caption)

album_upload()

ํƒœ๊ทธ: ,

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ:

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ