diff --git a/instaloader/__main__.py b/instaloader/__main__.py index d59473c..ad66827 100644 --- a/instaloader/__main__.py +++ b/instaloader/__main__.py @@ -207,8 +207,8 @@ def _main(instaloader: Instaloader, targetlist: List[str], if len(profiles) > 1: instaloader.context.log("Downloading {} profiles: {}".format(len(profiles), ' '.join([p.username for p in profiles]))) - if profiles and download_profile_pic and not instaloader.context.is_logged_in: - instaloader.context.error("Warning: Use --login to download HD version of profile pictures.") + if ((profiles and download_profile_pic) or download_posts) and not instaloader.context.is_logged_in: + instaloader.context.error("Warning: Use --login to download higher-quality versions of pictures.") instaloader.download_profiles(profiles, download_profile_pic, download_posts, download_tagged, download_igtv, download_highlights, download_stories, diff --git a/instaloader/instaloadercontext.py b/instaloader/instaloadercontext.py index bb13cc9..0ac2f0f 100644 --- a/instaloader/instaloadercontext.py +++ b/instaloader/instaloadercontext.py @@ -113,7 +113,7 @@ class InstaloaderContext: def close(self): """Print error log and close session""" if self.error_log and not self.quiet: - print("\nErrors occurred:", file=sys.stderr) + print("\nErrors or warnings occurred:", file=sys.stderr) for err in self.error_log: print(err, file=sys.stderr) self._session.close() @@ -536,8 +536,8 @@ class InstaloaderContext: .. versionadded:: 4.2.1""" with copy_session(self._session, self.request_timeout) as tempsession: - tempsession.headers['User-Agent'] = 'Instagram 10.3.2 (iPhone7,2; iPhone OS 9_3_3; en_US; en-US; ' \ - 'scale=2.00; 750x1334) AppleWebKit/420+' + tempsession.headers['User-Agent'] = 'Instagram 123.1.0.26.115 (iPhone12,1; iOS 13_3; en_US; en-US; ' \ + 'scale=2.00; 1656x3584; 190542906)' for header in ['Host', 'Origin', 'X-Instagram-AJAX', 'X-Requested-With']: tempsession.headers.pop(header, None) return self.get_json(path, params, 'i.instagram.com', tempsession) diff --git a/instaloader/structures.py b/instaloader/structures.py index bced2b7..a5245cc 100644 --- a/instaloader/structures.py +++ b/instaloader/structures.py @@ -71,6 +71,10 @@ class Post: self._full_metadata_dict = None # type: Optional[Dict[str, Any]] self._rhx_gis_str = None # type: Optional[str] self._location = None # type: Optional[PostLocation] + self._iphone_struct_ = None + if 'iphone_struct' in node: + # if loaded from JSON with load_structure_from_file() + self._iphone_struct_ = node['iphone_struct'] @classmethod def from_shortcode(cls, context: InstaloaderContext, shortcode: str): @@ -111,6 +115,8 @@ class Post: node['owner'] = self.owner_profile._asdict() if self._location: node['location'] = self._location._asdict() + if self._iphone_struct_: + node['iphone_struct'] = self._iphone_struct_ return node @property @@ -160,6 +166,15 @@ class Post: self._obtain_metadata() return self._rhx_gis_str + @property + def _iphone_struct(self) -> Dict[str, Any]: + if not self._context.is_logged_in: + raise LoginRequiredException("--login required to access iPhone media info endpoint.") + if not self._iphone_struct_: + data = self._context.get_iphone_json(path='api/v1/media/{}/info/'.format(self.mediaid), params={}) + self._iphone_struct_ = data['items'][0] + return self._iphone_struct_ + def _field(self, *keys) -> Any: """Lookups given fields in _node, and if not found in _full_metadata. Raises KeyError if not found anywhere.""" try: @@ -225,6 +240,11 @@ class Post: @property def url(self) -> str: """URL of the picture / video thumbnail of the post""" + if self.typename == "GraphImage" and self._context.is_logged_in: + try: + return self._iphone_struct['image_versions2']['candidates'][0]['url'] + except (InstaloaderException, KeyError, IndexError) as err: + self._context.error('{} Unable to fetch high quality image version of {}.'.format(err, self)) return self._node["display_url"] if "display_url" in self._node else self._node["display_src"] @property @@ -239,10 +259,17 @@ class Post: if any(edge['node']['is_video'] for edge in edges): # video_url is only present in full metadata, issue #558. edges = self._full_metadata['edge_sidecar_to_children']['edges'] - for edge in edges: + for idx, edge in enumerate(edges): node = edge['node'] is_video = node['is_video'] - yield PostSidecarNode(is_video=is_video, display_url=node['display_url'], + display_url = node['display_url'] + if not is_video and self._context.is_logged_in: + try: + carousel_media = self._iphone_struct['carousel_media'] + display_url = carousel_media[idx]['image_versions2']['candidates'][0]['url'] + except (InstaloaderException, KeyError, IndexError) as err: + self._context.error('{} Unable to fetch high quality image version of {}.'.format(err, self)) + yield PostSidecarNode(is_video=is_video, display_url=display_url, video_url=node['video_url'] if is_video else None) @property