fix: add mobile user-agent and random delays to bypass Instagram anti-bot
- iPhone Safari user-agent + X-IG-App-ID header - 2-6s random delay between profile checks - 1-3s delay between media downloads - RateController for built-in throttling - Try/except per followee to not stop on errors
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import http.cookiejar
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
import time
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import AsyncIterator
|
||||
@@ -22,8 +24,16 @@ class InstagramMonitor:
|
||||
compress_json=False,
|
||||
post_metadata_txt_pattern="",
|
||||
max_connection_attempts=3,
|
||||
request_timeout=30,
|
||||
request_timeout=60,
|
||||
rate_controller=instaloader.RateController(),
|
||||
)
|
||||
self.loader.context._session.headers.update({
|
||||
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
|
||||
"X-IG-App-ID": "936619743392459",
|
||||
"X-IG-WWW-Claim": "0",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
})
|
||||
self._session_path = Path(config.session_file)
|
||||
self._download_dir = Path(config.download_dir)
|
||||
self._state_file = self._download_dir / "state.json"
|
||||
@@ -153,6 +163,11 @@ class InstagramMonitor:
|
||||
"""Clear session cookies to start fresh."""
|
||||
self.loader.context._session.cookies.clear()
|
||||
|
||||
def _random_delay(self, min_sec: float = 2.0, max_sec: float = 5.0) -> None:
|
||||
"""Random delay to avoid detection."""
|
||||
delay = random.uniform(min_sec, max_sec)
|
||||
time.sleep(delay)
|
||||
|
||||
def _load_cookies_from_json(self, path: Path) -> None:
|
||||
with open(path) as f:
|
||||
cookies = json.load(f)
|
||||
@@ -228,6 +243,8 @@ class InstagramMonitor:
|
||||
logger.error("Cannot check updates without login")
|
||||
return
|
||||
|
||||
self._random_delay(3, 7)
|
||||
|
||||
try:
|
||||
# First verify who we are logged in as
|
||||
logger.info(f"Attempting to fetch profile: {config.instagram_username}")
|
||||
@@ -253,32 +270,44 @@ class InstagramMonitor:
|
||||
for followee in followees:
|
||||
username = followee.username
|
||||
|
||||
for story in self._get_profile_stories(username):
|
||||
media_path = self._download_media(story)
|
||||
if media_path:
|
||||
self._state[str(story.mediaid)] = datetime.utcnow().isoformat()
|
||||
self._save_state()
|
||||
yield {
|
||||
"type": "story",
|
||||
"username": username,
|
||||
"media_path": media_path,
|
||||
"caption": "",
|
||||
"shortcode": str(story.mediaid),
|
||||
}
|
||||
self._random_delay(3, 6)
|
||||
|
||||
for post in self._get_profile_posts(username):
|
||||
caption = post.caption or ""
|
||||
media_path = self._download_media(post)
|
||||
if media_path:
|
||||
self._state[str(post.mediaid)] = datetime.utcnow().isoformat()
|
||||
self._save_state()
|
||||
yield {
|
||||
"type": "post",
|
||||
"username": username,
|
||||
"media_path": media_path,
|
||||
"caption": caption[:500],
|
||||
"shortcode": post.shortcode,
|
||||
}
|
||||
try:
|
||||
for story in self._get_profile_stories(username):
|
||||
media_path = self._download_media(story)
|
||||
if media_path:
|
||||
self._state[str(story.mediaid)] = datetime.utcnow().isoformat()
|
||||
self._save_state()
|
||||
yield {
|
||||
"type": "story",
|
||||
"username": username,
|
||||
"media_path": media_path,
|
||||
"caption": "",
|
||||
"shortcode": str(story.mediaid),
|
||||
}
|
||||
self._random_delay(1, 3)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing stories for {username}: {e}")
|
||||
|
||||
self._random_delay(2, 4)
|
||||
|
||||
try:
|
||||
for post in self._get_profile_posts(username):
|
||||
caption = post.caption or ""
|
||||
media_path = self._download_media(post)
|
||||
if media_path:
|
||||
self._state[str(post.mediaid)] = datetime.utcnow().isoformat()
|
||||
self._save_state()
|
||||
yield {
|
||||
"type": "post",
|
||||
"username": username,
|
||||
"media_path": media_path,
|
||||
"caption": caption[:500],
|
||||
"shortcode": post.shortcode,
|
||||
}
|
||||
self._random_delay(2, 5)
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing posts for {username}: {e}")
|
||||
|
||||
def cleanup_downloads(self, max_age_hours: int = 24) -> None:
|
||||
now = datetime.utcnow()
|
||||
|
||||
Reference in New Issue
Block a user