1
0
mirror of https://github.com/instaloader/instaloader.git synced 2024-10-05 14:57:08 +02:00

Download stories using GraphQL queries

As suggested in #71, stories are now fetched using GraphQL queries.
This obviates the need of pretending to be a smartphone app and to do
some voodoo to the headers.
This commit is contained in:
André Koch-Kramer 2018-03-18 20:06:19 +01:00
parent 77a44362aa
commit c1b9aa5fba

View File

@ -1234,33 +1234,18 @@ class Instaloader:
:param userids: List of user IDs to be processed in terms of downloading their stories, or None. :param userids: List of user IDs to be processed in terms of downloading their stories, or None.
""" """
tempsession = copy_session(self.session)
header = tempsession.headers
header['User-Agent'] = 'Instagram 10.3.2 (iPhone7,2; iPhone OS 9_3_3; en_US; en-US; scale=2.00; 750x1334) ' \
'AppleWebKit/420+'
del header['Host']
del header['Origin']
del header['X-Instagram-AJAX']
del header['X-Requested-With']
def _get(url): if userids is None:
self._sleep() data = self.graphql_query("d15efd8c0c5b23f0ef71f18bf363c704", {"only_stories": True})["data"]["user"]
resp = tempsession.get(url) if data is None:
if resp.status_code != 200: raise BadResponseException('Bad stories reel JSON.')
raise ConnectionException('Failed to fetch stories.') userids = list(edge["node"]["id"] for edge in data["feed_reels_tray"]["edge_reels_tray_to_reel"]["edges"])
return json.loads(resp.text)
url_reel_media = 'https://i.instagram.com/api/v1/feed/user/{0}/reel_media/' stories = self.graphql_query("bf41e22b1c4ba4c9f31b844ebb7d9056",
url_reels_tray = 'https://i.instagram.com/api/v1/feed/reels_tray/' {"reel_ids": userids, "precomposed_overlay": False})["data"]
if userids is not None:
for userid in userids: for media in stories["reels_media"]:
yield _get(url_reel_media.format(userid)) yield media
else:
data = _get(url_reels_tray)
if 'tray' not in data:
raise BadResponseException('Bad story reel JSON.')
for user in data["tray"]:
yield user if "items" in user else _get(url_reel_media.format(user['user']['pk']))
@_requires_login @_requires_login
def download_stories(self, def download_stories(self,
@ -1308,9 +1293,9 @@ class Instaloader:
:return: True if something was downloaded, False otherwise, i.e. file was already there :return: True if something was downloaded, False otherwise, i.e. file was already there
""" """
shortcode = item["code"] if "code" in item else "no_code" shortcode = mediaid_to_shortcode(int(item["id"]))
date_local = datetime.fromtimestamp(item["taken_at"]) date_local = datetime.fromtimestamp(item["taken_at_timestamp"])
date_utc = datetime.utcfromtimestamp(item["taken_at"]) date_utc = datetime.utcfromtimestamp(item["taken_at_timestamp"])
dirname = self.dirname_pattern.format(profile=profile, target=target) dirname = self.dirname_pattern.format(profile=profile, target=target)
filename = dirname + '/' + self.filename_pattern.format(profile=profile, target=target, filename = dirname + '/' + self.filename_pattern.format(profile=profile, target=target,
date_utc=date_utc, date_utc=date_utc,
@ -1320,32 +1305,17 @@ class Instaloader:
shortcode=shortcode) shortcode=shortcode)
os.makedirs(os.path.dirname(filename), exist_ok=True) os.makedirs(os.path.dirname(filename), exist_ok=True)
downloaded = False downloaded = False
if "image_versions2" in item: if not item["is_video"] or self.download_video_thumbnails is Tristate.always:
if "video_versions" not in item or self.download_video_thumbnails is Tristate.always: url = item["display_resources"][-1]["src"]
url = item["image_versions2"]["candidates"][0]["url"] downloaded = self.download_pic(filename=filename,
downloaded = self.download_pic(filename=filename, filename_alt=filename_old,
filename_alt=filename_old, url=url,
url=url, mtime=date_local)
mtime=date_local) if item["is_video"] and self.download_videos is Tristate.always:
else:
self._log("Warning: Unable to find story image.")
if "caption" in item and item["caption"] is not None and \
self.save_captions is not Tristate.never:
caption = item["caption"]
if isinstance(caption, dict) and "text" in caption:
caption = caption["text"]
self.save_caption(filename=filename, filename_alt=filename_old, mtime=date_local, caption=caption)
else:
self._log("<no caption>", end=' ', flush=True)
if "video_versions" in item and self.download_videos is Tristate.always:
downloaded |= self.download_pic(filename=filename, downloaded |= self.download_pic(filename=filename,
filename_alt=filename_old, filename_alt=filename_old,
url=item["video_versions"][0]["url"], url=item["video_resources"][-1]["src"],
mtime=date_local) mtime=date_local)
if item["story_locations"] and self.download_geotags is not Tristate.never:
location = item["story_locations"][0]["location"]
if location:
self.save_location(filename, location, date_local)
self._log() self._log()
return downloaded return downloaded