diff --git a/docs/as-module.rst b/docs/as-module.rst index 79c545c..5dcac44 100644 --- a/docs/as-module.rst +++ b/docs/as-module.rst @@ -198,6 +198,8 @@ Exceptions .. autoexception:: BadCredentialsException +.. autoexception:: PostChangedException + .. autoexception:: TooManyRequestsException ``InstaloaderContext`` (Low-level functions) diff --git a/instaloader/exceptions.py b/instaloader/exceptions.py index 5041f3a..0fc7196 100644 --- a/instaloader/exceptions.py +++ b/instaloader/exceptions.py @@ -57,5 +57,10 @@ class ConnectionException(InstaloaderException): pass +class PostChangedException(InstaloaderException): + """.. versionadded:: 4.2.2""" + pass + + class TooManyRequestsException(ConnectionException): pass diff --git a/instaloader/instaloader.py b/instaloader/instaloader.py index 5c4c65e..15248f0 100644 --- a/instaloader/instaloader.py +++ b/instaloader/instaloader.py @@ -939,8 +939,22 @@ class Instaloader: self.context.log('') continue with self.context.error_catcher("Download {} of {}".format(post, profile_name)): - downloaded = self.download_post(post, target=profile_name) - if fast_update and not downloaded: + # The PostChangedException gets raised if the Post's id/shortcode changed while obtaining + # additional metadata. This is most likely the case if a HTTP redirect takes place while + # resolving the shortcode URL. + # The `post_changed` variable keeps the fast-update functionality alive: A Post which is + # obained after a redirect has probably already been downloaded as a previous Post of the + # same Profile. + # Observed in issue #225: https://github.com/instaloader/instaloader/issues/225 + post_changed = False + while True: + try: + downloaded = self.download_post(post, target=profile_name) + break + except PostChangedException: + post_changed = True + continue + if fast_update and not downloaded and not post_changed: break if stories and profiles: diff --git a/instaloader/structures.py b/instaloader/structures.py index 22f0465..4a7d0b2 100644 --- a/instaloader/structures.py +++ b/instaloader/structures.py @@ -128,6 +128,9 @@ class Post: pic_json = self._context.get_json("p/{0}/".format(self.shortcode), params={}) self._full_metadata_dict = pic_json['entry_data']['PostPage'][0]['graphql']['shortcode_media'] self._rhx_gis_str = pic_json['rhx_gis'] + if self.mediaid != self._full_metadata_dict['id']: + self._node.update(self._full_metadata_dict) + raise PostChangedException @property def _full_metadata(self) -> Dict[str, Any]: