๋ชฉ์ฐจ
ํ์ด์ฌ ์ธ์คํ๊ทธ๋จ ์ฌ์ง ๋ค์ด๋ก๋ ์คํฌ๋ฆฝํธ ๋ง๋ค๊ธฐ
์ธ์คํ๊ทธ๋จ์ ๊ตฌ์กฐ๊ฐ ์์ฃผ ๋ฐ๋๊ณ ๊ณต์ API๋ฅผ ์ฐ๋ ค๋ฉด ์ฑ ๋ฑ๋ก ๋ฐ ํ ํฐ ๋ฐ๊ธ ์ ์ฐจ๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์, ๊ฐ์ฅ ์์ ์ ์ผ๋ก ์ฌ์ง์ ๋ค์ด๋ก๋ํ ์ ์๋ ๋ฐฉ๋ฒ์ Instaloader ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ์ด ์คํฌ๋ฆฝํธ๋ ๊ณต๊ฐ ๊ณ์ ์ ๋ก๊ทธ์ธ ์์ด, ๋น๊ณต๊ฐ ๊ณ์ ์ ๋ก๊ทธ์ธ ํ์ ์ฌ์ง์ ๋ค์ด๋ก๋ํ ์ ์๋๋ก ์ค๊ณ๋์ด ์์ต๋๋ค.
์๋ ์์ ๋ฅผ ์ฐธ๊ณ ํ์๊ณ , ํ์์ ๋ฐ๋ผ ์ต์ ์ ์กฐ์ ํ์ฌ ์ฌ์ฉํ์ธ์.
# ๋จผ์ Instaloader ์ค์น
pip install instaloader
ํ์ด์ฌ ์ธ์คํ๊ทธ๋จ ์ฌ์ง ๋ค์ด๋ก๋ ์คํฌ๋ฆฝํธ ์์ค์ฝ๋
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
instagram_downloader.py
Instaloader๋ฅผ ์ด์ฉํด ์ธ์คํ๊ทธ๋จ ์ฌ์ง์ ์๋์ผ๋ก ๋ค์ด๋ก๋ํ๋ ์คํฌ๋ฆฝํธ์
๋๋ค.
Usage:
# ๊ณต๊ฐ ๊ณ์ ๋ค์ด๋ก๋
python instagram_downloader.py --target naver
# ๋น๊ณต๊ฐ ๊ณ์ ๋ค์ด๋ก๋ (๋ก๊ทธ์ธ ํ์)
python instagram_downloader.py --target your_private_account \
--login --username your_id --password your_pw
# ํน์ ๊ฒ์๋ฌผ URL๋ง ๋ค์ด๋ก๋
python instagram_downloader.py --post-url https://www.instagram.com/p/CG0UU3PnR3Z/
"""
import os
import argparse
import instaloader
def download_profile(loader, username, output_dir):
"""ํ๋กํ ์ ์ฒด ๋ค์ด๋ก๋"""
profile = instaloader.Profile.from_username(loader.context, username)
target_dir = os.path.join(output_dir, username)
os.makedirs(target_dir, exist_ok=True)
print(f"[+] '{username}' ํ๋กํ์์ ๊ฒ์๋ฌผ ๊ฐ์ ธ์ค๋ ์ค...")
for post in profile.get_posts():
print(f" → {post.shortcode}", end=" ")
loader.download_post(post, target=target_dir)
print("์๋ฃ")
def download_post(loader, post_url, output_dir):
"""๋จ์ผ ๊ฒ์๋ฌผ ๋ค์ด๋ก๋"""
shortcode = post_url.rstrip("/").split("/")[-1]
post = instaloader.Post.from_shortcode(loader.context, shortcode)
target_dir = os.path.join(output_dir, shortcode)
os.makedirs(target_dir, exist_ok=True)
print(f"[+] ๊ฒ์๋ฌผ {shortcode} ๋ค์ด๋ก๋ ์ค...")
loader.download_post(post, target=target_dir)
print("์๋ฃ")
def main():
parser = argparse.ArgumentParser(
description="Instaloader ๊ธฐ๋ฐ ์ธ์คํ๊ทธ๋จ ์ฌ์ง ๋ค์ด๋ก๋ ์คํฌ๋ฆฝํธ"
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--target", help="์ฌ์ฉ์ ๊ณ์ ๋ช
(username)")
group.add_argument("--post-url", help="๋ค์ด๋ก๋ํ ๊ฒ์๋ฌผ URL")
parser.add_argument("--login", action="store_true", help="๋น๊ณต๊ฐ ๊ณ์ ๋ค์ด๋ก๋๋ฅผ ์ํด ๋ก๊ทธ์ธ")
parser.add_argument("--username", help="์ธ์คํ๊ทธ๋จ ๋ก๊ทธ์ธ ์์ด๋")
parser.add_argument("--password", help="์ธ์คํ๊ทธ๋จ ๋ก๊ทธ์ธ ๋น๋ฐ๋ฒํธ")
parser.add_argument("--output-dir", default="downloads", help="์ ์ฅ ํด๋ (๊ธฐ๋ณธ: downloads)")
args = parser.parse_args()
loader = instaloader.Instaloader(
download_comments=False,
save_metadata=False,
post_metadata_txt_pattern="", # ๋ฉํ๋ฐ์ดํฐ ํ
์คํธ ํ์ผ ๋ฏธ์์ฑ
dirname_pattern="{target}" # ๋ค์ด๋ก๋ ๋๋ ํ ๋ฆฌ ํจํด
)
# ๋ก๊ทธ์ธ ์ฒ๋ฆฌ
if args.login:
if not (args.username and args.password):
parser.error("๋ก๊ทธ์ธ์ ์ฌ์ฉํ๋ ค๋ฉด --username ๊ณผ --password ๋ฅผ ๋ชจ๋ ์ง์ ํด์ผ ํฉ๋๋ค.")
print("[*] ๋ก๊ทธ์ธ ์๋ ์ค...")
loader.login(args.username, args.password)
print("[+] ๋ก๊ทธ์ธ ์ฑ๊ณต")
os.makedirs(args.output_dir, exist_ok=True)
os.chdir(args.output_dir)
# ์คํ ๋ถ๊ธฐ
if args.post_url:
download_post(loader, args.post_url, ".")
else:
download_profile(loader, args.target, ".")
if __name__ == "__main__":
main()
์ฌ์ฉ๋ฐฉ๋ฒ ์์ฝ
- Instaloader ์ค์น
- bashpip install instaloader
- ๋ณต์ฌํธ์ง
- ์คํฌ๋ฆฝํธ ์คํ ๊ถํ ๋ถ์ฌ (Linux/Mac)
- bashchmod +x instagram_downloader.py
- ๋ณต์ฌํธ์ง
- ๊ณต๊ฐ ๊ณ์ ์ ์ฒด ๋ค์ด๋ก๋
- bashpython instagram_downloader.py --target instagram_username
- ๋ณต์ฌํธ์ง
- ๋น๊ณต๊ฐ ๊ณ์ ๋ค์ด๋ก๋ (๋ก๊ทธ์ธ ํ์)
- bashpython instagram_downloader.py --target private_username \ --login --username your_id --password your_pw
- ๋ณต์ฌํธ์ง
- ํน์ ๊ฒ์๋ฌผ(URL)๋ง ๋ค์ด๋ก๋
- bashpython instagram_downloader.py --post-url https://www.instagram.com/p/๊ฒ์๋ฌผ์ฝ๋/
- ๋ณต์ฌํธ์ง
์ด ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ๋ฉด ๊ฐ๋จํ ๋ช ๋ น์ด๋ง์ผ๋ก ์ํ๋ ๊ณ์ ์ด๋ ๊ฒ์๋ฌผ์ ์ฌ์ง์ ์์ฝ๊ฒ ๋ก์ปฌ์ ์ ์ฅํ ์ ์์ต๋๋ค. ํ์์ ๋ฐ๋ผ Instaloader์ ์ถ๊ฐ ์ต์ (์: ๋์์ ํฌํจ, ์คํ ๋ฆฌ ๋ค์ด๋ก๋ ๋ฑ)์ ๊ณต์ ๋ฌธ์์์ ํ์ธํด ์ ์ฉํด ๋ณด์ธ์.
o4-mini-high
๋์ ๋ง:
[+] ๊ฒ์๋ฌผ DIgK0tCxApJ ๋ค์ด๋ก๋ ์ค...
python : Traceback (most recent call last):
์์น ์ค:1 ๋ฌธ์:1
+ python instagram_downloader.py --post-url https://www.instagram.com/p ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Traceback (most recent call last)::String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
File "D:\WorkPY\InstaDownload\instagram_downloader.py", line 86, in <module>
main()
~~~~^^
File "D:\WorkPY\InstaDownload\instagram_downloader.py", line 81, in main
download_post(loader, args.post_url, ".")
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\WorkPY\InstaDownload\instagram_downloader.py", line 44, in download_post
loader.download_post(post, target=target_dir)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\hidec\AppData\Local\Programs\Python\Python313\Lib\site-packages\instaloader\instaloader.py", line 745, in download_post
downloaded &= self.download_pic(filename=sidecar_filename, url=sidecar_node.display_url,
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
mtime=post.date_local, filename_suffix=suffix)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\hidec\AppData\Local\Programs\Python\Python313\Lib\site-packages\instaloader\instaloader.py", line 97, in call
return func(instaloader, *args, **kwargs)
File "C:\Users\hidec\AppData\Local\Programs\Python\Python313\Lib\site-packages\instaloader\instaloader.py", line 356, in download_pic
self.context.write_raw(resp, filename)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
File "C:\Users\hidec\AppData\Local\Programs\Python\Python313\Lib\site-packages\instaloader\instaloadercontext.py", line 657, in write_raw
self.log(filename, end=' ', flush=True)
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\hidec\AppData\Local\Programs\Python\Python313\Lib\site-packages\instaloader\instaloadercontext.py", line 141, in log
print(*msg, sep=sep, end=end, flush=flush)
~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeEncodeError: 'cp949' codec can't encode character '\u2024' in position 0: illegal multibyte sequence
ChatGPT์ ๋ง:
5์ด ๋์ ์๊ฐํจ
์ธ์ฝ๋ฉ ๋ฌธ์ ๋ Windows ์ฝ์์ ๊ธฐ๋ณธ cp949 ์ธ์ฝ๋ฉ์ด U+2024(โค) ๊ฐ์ ์ ๋์ฝ๋ ๋ฌธ์๋ฅผ ์ฒ๋ฆฌํ์ง ๋ชปํด์ ๋ฐ์ํ๋ ์๋ฌ์ ๋๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ํด๊ฒฐ์ฑ ์ ์คํฌ๋ฆฝํธ ์ต์๋จ์์ stdout/stderr ์ ์ธ์ฝ๋ฉ์ UTF-8 ๋ก ์ฌ๊ตฌ์ฑํด ์ฃผ๋ ๊ฒ์ ๋๋ค. ์๋ ํจ์น๋ฅผ ์ ์ฉํด ๋ณด์ธ์.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
instagram_downloader.py
@@
import os
import argparse
import instaloader
+import sys
+### Windows ์ฝ์์์๋ ์ ๋์ฝ๋ ๊นจ์ง ์์ด ์ถ๋ ฅ๋๋๋ก stdout/stderr ์ธ์ฝ๋ฉ ์ฌ๊ตฌ์ฑ ###
+try:
+ # Python 3.7 ์ด์
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
+ sys.stderr.reconfigure(encoding="utf-8", errors="replace")
+except AttributeError:
+ # ํ์ ํธํ
+ import io
+ sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", errors="replace")
+ sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")
+
def download_profile(loader, username, output_dir):
"""ํ๋กํ ์ ์ฒด ๋ค์ด๋ก๋"""
profile = instaloader.Profile.from_username(loader.context, username)
์ด๋ ๊ฒ ํ๋ฉด loader.context.log() ๋ ์ผ๋ฐ print() ํธ์ถ ์์๋ UTF-8๋ก ์์ ํ๊ฒ ์ถ๋ ฅ๋์ด ๋ ์ด์ cp949 codec ์๋ฌ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
–––
์ถ๊ฐ ํ
ํ์ด์ฌ ์คํ ์ -X utf8 ํ๋๊ทธ๋ฅผ ์ฃผ๋ฉด(python -X utf8 instagram_downloader.py …) ์ ์ฒด I/O์ UTF-8 ๋ชจ๋๋ฅผ ๊ฐ์ ๋ก ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
- Windows ํฐ๋ฏธ๋(๋๋ PowerShell)์์ chcp 65001 ๋ช ๋ น์ผ๋ก ์ฝ์ ์ธ์ฝ๋ฉ์ UTF-8 ๋ก ๋ณ๊ฒฝํ ๋ค ์คํํด๋ ๋์ผํ ํจ๊ณผ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
๋๊ธ