def media_info_a1(self, media_pk: int, max_id: str = None) -> Media: """ Get Media from PK Parameters ---------- media_pk: int Unique identifier of the media max_id: str, optional Max ID, default value is None Returns ------- Media An object of Media type """ media_pk = self.media_pk(media_pk) shortcode = InstagramIdCodec.encode(media_pk) """Use Client.media_info """ params = {"max_id": max_id} if max_id else None data = self.public_a1_request( "/p/{shortcode!s}/".format(**{"shortcode": shortcode}), params=params) if not data.get("shortcode_media"): raise MediaNotFound(media_pk=media_pk, **data) return extract_media_gql(data["shortcode_media"])
def media_info_gql(self, media_pk: int) -> Media: """ Get Media from PK Parameters ---------- media_pk: int Unique identifier of the media Returns ------- Media An object of Media type """ media_pk = self.media_pk(media_pk) shortcode = InstagramIdCodec.encode(media_pk) """Use Client.media_info """ variables = { "shortcode": shortcode, "child_comment_count": 3, "fetch_comment_count": 40, "parent_comment_count": 24, "has_threaded_comments": False, } data = self.public_graphql_request( variables, query_hash="477b65a610463740ccdb83135b2014db") if not data.get("shortcode_media"): raise MediaNotFound(media_pk=media_pk, **data) if data["shortcode_media"]["location"]: data["shortcode_media"]["location"] = self.location_complete( extract_location(data["shortcode_media"]["location"])).dict() return extract_media_gql(data["shortcode_media"])
def hashtag_medias_a1_chunk( self, name: str, max_amount: int = 27, tab_key: str = "", end_cursor: str = None ) -> Tuple[List[Media], str]: """ Get chunk of medias and end_cursor by Public Web API Parameters ---------- name: str Name of the hashtag max_amount: int, optional Maximum number of media to return, default is 27 tab_key: str, optional Tab Key, default value is "" end_cursor: str, optional End Cursor, default value is None Returns ------- Tuple[List[Media], str] List of objects of Media and end_cursor """ unique_set = set() medias = [] while True: data = self.public_a1_request( f"/explore/tags/{name}/", params={"max_id": end_cursor} if end_cursor else {}, )["hashtag"] page_info = data["edge_hashtag_to_media"]["page_info"] end_cursor = page_info["end_cursor"] edges = data[tab_key]["edges"] for edge in edges: if max_amount and len(medias) >= max_amount: break # check uniq media_pk = edge["node"]["id"] if media_pk in unique_set: continue unique_set.add(media_pk) # check contains hashtag in caption media = extract_media_gql(edge["node"]) if f"#{name}" not in media.caption_text: continue # Enrich media: Full user, usertags and video_url medias.append(self.media_info_gql(media_pk)) ###################################################### # infinity loop in hashtag_medias_top_a1 # https://github.com/adw0rd/instagrapi/issues/52 ###################################################### # Mikhail Andreev, [30.12.20 02:17]: # Instagram always returns the same 9 medias for top # I think we should return them without a loop ###################################################### # if not page_info["has_next_page"] or not end_cursor: # break # if max_amount and len(medias) >= max_amount: # break break return medias, end_cursor
def usertag_medias_gql(self, user_id: int, amount: int = 0, sleep: int = 2) -> List[Media]: """ Get medias where a user is tagged (by Public GraphQL API) Parameters ---------- user_id: int amount: int, optional Maximum number of media to return, default is 0 (all medias) sleep: int, optional Timeout between pages iterations, default is 2 Returns ------- List[Media] A list of objects of Media """ amount = int(amount) user_id = int(user_id) medias = [] end_cursor = None variables = { "id": user_id, "first": 50 if not amount or amount > 50 else amount, # These are Instagram restrictions, you can only specify <= 50 } while True: if end_cursor: variables["after"] = end_cursor data = self.public_graphql_request( variables, query_hash="be13233562af2d229b008d2976b998b5") page_info = json_value(data, "user", "edge_user_to_photos_of_you", "page_info", default={}) edges = json_value(data, "user", "edge_user_to_photos_of_you", "edges", default=[]) for edge in edges: medias.append(edge["node"]) end_cursor = page_info.get("end_cursor") if not page_info.get("has_next_page") or not end_cursor: break if amount and len(medias) >= amount: break time.sleep(sleep) if amount: medias = medias[:amount] return [extract_media_gql(media) for media in medias]
def user_medias_gql(self, user_id: int, amount: int = 50, sleep: int = 2) -> List[Media]: """ Get a user's media by Public Graphql API Parameters ---------- user_id: int amount: int, optional Maximum number of media to return, default is 50 sleep: int, optional Timeout between pages iterations, default is 2 Returns ------- List[Media] A list of objects of Media """ amount = int(amount) user_id = int(user_id) medias = [] end_cursor = None variables = { "id": user_id, "first": 50 if amount > 50 else amount, # These are Instagram restrictions, you can only specify <= 50 } while True: if end_cursor: variables["after"] = end_cursor data = self.public_graphql_request( variables, query_hash="e7e2f4da4b02303f74f0841279e52d76") page_info = json_value(data, "user", "edge_owner_to_timeline_media", "page_info", default={}) edges = json_value(data, "user", "edge_owner_to_timeline_media", "edges", default=[]) for edge in edges: medias.append(edge["node"]) end_cursor = page_info.get("end_cursor") if not page_info.get("has_next_page") or not end_cursor: break if len(medias) >= amount: break time.sleep(sleep) return [extract_media_gql(media) for media in medias[:amount]]
def user_medias_paginated_gql(self, user_id: int, amount: int = 0, sleep: int = 2, end_cursor=None) -> Tuple[List[Media], str]: """ Get a page of a user's media by Public Graphql API Parameters ---------- user_id: int amount: int, optional Maximum number of media to return, default is 0 (all medias) sleep: int, optional Timeout between pages iterations, default is 2 end_cursor: str, optional Cursor value to start at, obtained from previous call to this method Returns ------- Tuple[List[Media], str] A tuple containing a list of medias and the next end_cursor value """ amount = int(amount) user_id = int(user_id) medias = [] variables = { "id": user_id, "first": 50 if not amount or amount > 50 else amount, # These are Instagram restrictions, you can only specify <= 50 } variables["after"] = end_cursor data = self.public_graphql_request( variables, query_hash="e7e2f4da4b02303f74f0841279e52d76") page_info = json_value(data, "user", "edge_owner_to_timeline_media", "page_info", default={}) edges = json_value(data, "user", "edge_owner_to_timeline_media", "edges", default=[]) for edge in edges: medias.append(edge["node"]) end_cursor = page_info.get("end_cursor") if amount: medias = medias[:amount] return ([extract_media_gql(media) for media in medias], end_cursor)
def hashtag_medias_a1(self, name: str, amount: int = 27, tab_key: str = '') -> List[Media]: """ Get medias for a hashtag Parameters ---------- name: str Name of the hashtag amount: int, optional Maximum number of media to return, default is 27 tab_key: str, optional Tab Key, default value is "" Returns ------- List[Media] List of objects of Media """ unique_set = set() medias = [] end_cursor = None while True: data = self.public_a1_request( f'/explore/tags/{name}/', params={"max_id": end_cursor} if end_cursor else {})['hashtag'] page_info = data["edge_hashtag_to_media"]["page_info"] end_cursor = page_info["end_cursor"] edges = data[tab_key]["edges"] for edge in edges: if amount and len(medias) >= amount: break # check uniq media_pk = edge['node']['id'] if media_pk in unique_set: continue unique_set.add(media_pk) # check contains hashtag in caption media = extract_media_gql(edge['node']) if f'#{name}' not in media.caption_text: continue # Enrich media: Full user, usertags and video_url medias.append(self.media_info_gql(media_pk)) ###################################################### # infinity loop in hashtag_medias_top_a1 # https://github.com/adw0rd/instagrapi/issues/52 ###################################################### # Mikhail Andreev, [30.12.20 02:17]: # Instagram always returns the same 9 medias for top # I think we should return them without a loop ###################################################### # if not page_info["has_next_page"] or not end_cursor: # break # if amount and len(medias) >= amount: # break break if amount: medias = medias[:amount] return medias