mirror of
https://github.com/instaloader/instaloader.git
synced 2024-09-11 16:22:24 +02:00
parent
caf75a8135
commit
591dfd31e4
@ -120,6 +120,9 @@ be downloaded.
|
|||||||
session cookies. Without this flag, they are stored in a path
|
session cookies. Without this flag, they are stored in a path
|
||||||
within your temporary directory, encoding your local
|
within your temporary directory, encoding your local
|
||||||
username and your instagram profile name.
|
username and your instagram profile name.
|
||||||
|
--no-profile-subdir Instead of creating a subdirectory for each profile and
|
||||||
|
storing pictures there, store pictures in files named
|
||||||
|
PROFILE__DATE_TIME.jpg.'
|
||||||
|
|
||||||
To get a list of all flags, run ``instaloader --help``.
|
To get a list of all flags, run ``instaloader --help``.
|
||||||
|
|
||||||
|
@ -133,12 +133,13 @@ def get_anonymous_session() -> requests.Session:
|
|||||||
|
|
||||||
class Instaloader:
|
class Instaloader:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
sleep: bool = True, quiet: bool = False, shorter_output: bool = False):
|
sleep: bool = True, quiet: bool = False, shorter_output: bool = False, profile_subdirs: bool = True):
|
||||||
self.session = get_anonymous_session()
|
self.session = get_anonymous_session()
|
||||||
self.username = None
|
self.username = None
|
||||||
self.sleep = sleep
|
self.sleep = sleep
|
||||||
self.quiet = quiet
|
self.quiet = quiet
|
||||||
self.shorter_output = shorter_output
|
self.shorter_output = shorter_output
|
||||||
|
self.profile_subdirs = profile_subdirs
|
||||||
|
|
||||||
def _log(self, *msg, sep='', end='\n', flush=False):
|
def _log(self, *msg, sep='', end='\n', flush=False):
|
||||||
if not self.quiet:
|
if not self.quiet:
|
||||||
@ -250,7 +251,10 @@ class Instaloader:
|
|||||||
outputlabel = _epoch_to_string(date_epoch)
|
outputlabel = _epoch_to_string(date_epoch)
|
||||||
urlmatch = re.search('\\.[a-z]*\\?', url)
|
urlmatch = re.search('\\.[a-z]*\\?', url)
|
||||||
file_extension = url[-3:] if urlmatch is None else urlmatch.group(0)[1:-1]
|
file_extension = url[-3:] if urlmatch is None else urlmatch.group(0)[1:-1]
|
||||||
filename = name.lower() + '/' + _epoch_to_string(date_epoch)
|
if self.profile_subdirs:
|
||||||
|
filename = name.lower() + '/' + _epoch_to_string(date_epoch)
|
||||||
|
else:
|
||||||
|
filename = name.lower() + '__' + _epoch_to_string(date_epoch)
|
||||||
if filename_suffix is not None:
|
if filename_suffix is not None:
|
||||||
filename += '_' + filename_suffix
|
filename += '_' + filename_suffix
|
||||||
filename += '.' + file_extension
|
filename += '.' + file_extension
|
||||||
@ -260,7 +264,8 @@ class Instaloader:
|
|||||||
resp = get_anonymous_session().get(url, stream=True)
|
resp = get_anonymous_session().get(url, stream=True)
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
self._log(outputlabel, end=' ', flush=True)
|
self._log(outputlabel, end=' ', flush=True)
|
||||||
os.makedirs(name.lower(), exist_ok=True)
|
if self.profile_subdirs:
|
||||||
|
os.makedirs(name.lower(), exist_ok=True)
|
||||||
with open(filename, 'wb') as file:
|
with open(filename, 'wb') as file:
|
||||||
resp.raw.decode_content = True
|
resp.raw.decode_content = True
|
||||||
shutil.copyfileobj(resp.raw, file)
|
shutil.copyfileobj(resp.raw, file)
|
||||||
@ -271,7 +276,11 @@ class Instaloader:
|
|||||||
|
|
||||||
def save_caption(self, name: str, date_epoch: float, caption: str) -> None:
|
def save_caption(self, name: str, date_epoch: float, caption: str) -> None:
|
||||||
"""Updates picture caption"""
|
"""Updates picture caption"""
|
||||||
filename = name.lower() + '/' + _epoch_to_string(date_epoch) + '.txt'
|
# pylint:disable=too-many-branches
|
||||||
|
if self.profile_subdirs:
|
||||||
|
filename = name.lower() + '/' + _epoch_to_string(date_epoch) + '.txt'
|
||||||
|
else:
|
||||||
|
filename = name.lower() + '__' + _epoch_to_string(date_epoch) + '.txt'
|
||||||
pcaption = caption.replace('\n', ' ').strip()
|
pcaption = caption.replace('\n', ' ').strip()
|
||||||
caption = caption.encode("UTF-8")
|
caption = caption.encode("UTF-8")
|
||||||
if self.shorter_output:
|
if self.shorter_output:
|
||||||
@ -307,17 +316,22 @@ class Instaloader:
|
|||||||
self._log(pcaption, end=' ', flush=True)
|
self._log(pcaption, end=' ', flush=True)
|
||||||
except UnicodeEncodeError:
|
except UnicodeEncodeError:
|
||||||
self._log('txt', end=' ', flush=True)
|
self._log('txt', end=' ', flush=True)
|
||||||
os.makedirs(name.lower(), exist_ok=True)
|
if self.profile_subdirs:
|
||||||
|
os.makedirs(name.lower(), exist_ok=True)
|
||||||
with open(filename, 'wb') as text_file:
|
with open(filename, 'wb') as text_file:
|
||||||
shutil.copyfileobj(BytesIO(caption), text_file)
|
shutil.copyfileobj(BytesIO(caption), text_file)
|
||||||
os.utime(filename, (datetime.datetime.now().timestamp(), date_epoch))
|
os.utime(filename, (datetime.datetime.now().timestamp(), date_epoch))
|
||||||
|
|
||||||
def save_location(self, name: str, location_json: Dict[str, str], date_epoch: float) -> None:
|
def save_location(self, name: str, location_json: Dict[str, str], date_epoch: float) -> None:
|
||||||
filename = name.lower() + '/' + _epoch_to_string(date_epoch) + '_location.txt'
|
if self.profile_subdirs:
|
||||||
|
filename = name.lower() + '/' + _epoch_to_string(date_epoch) + '_location.txt'
|
||||||
|
else:
|
||||||
|
filename = name.lower() + '__' + _epoch_to_string(date_epoch) + '_location.txt'
|
||||||
location_string = (location_json["name"] + "\n" +
|
location_string = (location_json["name"] + "\n" +
|
||||||
"https://maps.google.com/maps?q={0},{1}&ll={0},{1}\n".format(location_json["lat"],
|
"https://maps.google.com/maps?q={0},{1}&ll={0},{1}\n".format(location_json["lat"],
|
||||||
location_json["lng"]))
|
location_json["lng"]))
|
||||||
os.makedirs(name.lower(), exist_ok=True)
|
if self.profile_subdirs:
|
||||||
|
os.makedirs(name.lower(), exist_ok=True)
|
||||||
with open(filename, 'wb') as text_file:
|
with open(filename, 'wb') as text_file:
|
||||||
shutil.copyfileobj(BytesIO(location_string.encode()), text_file)
|
shutil.copyfileobj(BytesIO(location_string.encode()), text_file)
|
||||||
os.utime(filename, (datetime.datetime.now().timestamp(), date_epoch))
|
os.utime(filename, (datetime.datetime.now().timestamp(), date_epoch))
|
||||||
@ -327,7 +341,10 @@ class Instaloader:
|
|||||||
"""Downloads and saves profile pic with given url."""
|
"""Downloads and saves profile pic with given url."""
|
||||||
date_object = datetime.datetime.strptime(requests.head(url).headers["Last-Modified"],
|
date_object = datetime.datetime.strptime(requests.head(url).headers["Last-Modified"],
|
||||||
'%a, %d %b %Y %H:%M:%S GMT')
|
'%a, %d %b %Y %H:%M:%S GMT')
|
||||||
filename = name.lower() + '/' + _epoch_to_string(date_object.timestamp()) + '_UTC_profile_pic.' + url[-3:]
|
if self.profile_subdirs:
|
||||||
|
filename = name.lower() + '/' + _epoch_to_string(date_object.timestamp()) + '_UTC_profile_pic.' + url[-3:]
|
||||||
|
else:
|
||||||
|
filename = name.lower() + '__' + _epoch_to_string(date_object.timestamp()) + '_UTC_profile_pic.' + url[-3:]
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
self._log(filename + ' already exists')
|
self._log(filename + ' already exists')
|
||||||
return None
|
return None
|
||||||
@ -340,7 +357,8 @@ class Instaloader:
|
|||||||
resp = get_anonymous_session().get(url, stream=True)
|
resp = get_anonymous_session().get(url, stream=True)
|
||||||
if resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
self._log(filename)
|
self._log(filename)
|
||||||
os.makedirs(name.lower(), exist_ok=True)
|
if self.profile_subdirs:
|
||||||
|
os.makedirs(name.lower(), exist_ok=True)
|
||||||
with open(filename, 'wb') as file:
|
with open(filename, 'wb') as file:
|
||||||
resp.raw.decode_content = True
|
resp.raw.decode_content = True
|
||||||
shutil.copyfileobj(resp.raw, file)
|
shutil.copyfileobj(resp.raw, file)
|
||||||
@ -622,8 +640,12 @@ class Instaloader:
|
|||||||
"""
|
"""
|
||||||
profile_exists = len(json_data["entry_data"]) > 0 and "ProfilePage" in json_data["entry_data"]
|
profile_exists = len(json_data["entry_data"]) > 0 and "ProfilePage" in json_data["entry_data"]
|
||||||
is_logged_in = json_data["config"]["viewer"] is not None
|
is_logged_in = json_data["config"]["viewer"] is not None
|
||||||
|
if self.profile_subdirs:
|
||||||
|
id_filename = profile + "/id"
|
||||||
|
else:
|
||||||
|
id_filename = profile + "__id"
|
||||||
try:
|
try:
|
||||||
with open(profile + "/id", 'rb') as id_file:
|
with open(id_filename, 'rb') as id_file:
|
||||||
profile_id = int(id_file.read())
|
profile_id = int(id_file.read())
|
||||||
if (not profile_exists) or \
|
if (not profile_exists) or \
|
||||||
(profile_id != int(json_data['entry_data']['ProfilePage'][0]['user']['id'])):
|
(profile_id != int(json_data['entry_data']['ProfilePage'][0]['user']['id'])):
|
||||||
@ -642,8 +664,9 @@ class Instaloader:
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
if profile_exists:
|
if profile_exists:
|
||||||
os.makedirs(profile.lower(), exist_ok=True)
|
if self.profile_subdirs:
|
||||||
with open(profile + "/id", 'w') as text_file:
|
os.makedirs(profile.lower(), exist_ok=True)
|
||||||
|
with open(id_filename, 'w') as text_file:
|
||||||
profile_id = json_data['entry_data']['ProfilePage'][0]['user']['id']
|
profile_id = json_data['entry_data']['ProfilePage'][0]['user']['id']
|
||||||
text_file.write(profile_id + "\n")
|
text_file.write(profile_id + "\n")
|
||||||
self._log("Stored ID {0} for profile {1}.".format(profile_id, profile))
|
self._log("Stored ID {0} for profile {1}.".format(profile_id, profile))
|
||||||
@ -817,6 +840,9 @@ def main():
|
|||||||
parser.add_argument('-c', '--count',
|
parser.add_argument('-c', '--count',
|
||||||
help='Do not attempt to download more than COUNT posts. '
|
help='Do not attempt to download more than COUNT posts. '
|
||||||
'Applies only to #hashtag, :feed-all and :feed-liked.')
|
'Applies only to #hashtag, :feed-all and :feed-liked.')
|
||||||
|
parser.add_argument('--no-profile-subdir', action='store_true',
|
||||||
|
help='Instead of creating a subdirectory for each profile and storing pictures there, store '
|
||||||
|
'pictures in files named PROFILE__DATE_TIME.jpg.')
|
||||||
parser.add_argument('-S', '--no-sleep', action='store_true',
|
parser.add_argument('-S', '--no-sleep', action='store_true',
|
||||||
help='Do not sleep between actual downloads of pictures')
|
help='Do not sleep between actual downloads of pictures')
|
||||||
parser.add_argument('-O', '--shorter-output', action='store_true',
|
parser.add_argument('-O', '--shorter-output', action='store_true',
|
||||||
@ -826,7 +852,7 @@ def main():
|
|||||||
'if login credentials are needed but not given.')
|
'if login credentials are needed but not given.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
try:
|
try:
|
||||||
loader = Instaloader(not args.no_sleep, args.quiet, args.shorter_output)
|
loader = Instaloader(not args.no_sleep, args.quiet, args.shorter_output, not args.no_profile_subdir)
|
||||||
loader.download_profiles(args.profile, args.login, args.password, args.sessionfile,
|
loader.download_profiles(args.profile, args.login, args.password, args.sessionfile,
|
||||||
int(args.count) if args.count is not None else None,
|
int(args.count) if args.count is not None else None,
|
||||||
args.profile_pic_only, not args.skip_videos, args.geotags, args.fast_update)
|
args.profile_pic_only, not args.skip_videos, args.geotags, args.fast_update)
|
||||||
|
Loading…
Reference in New Issue
Block a user