4
4
#
5
5
# Instagram public API "scraper".
6
6
#
7
+ from typing import Dict , Iterator
8
+
7
9
import json
8
10
from urllib .parse import quote
9
11
from ebbe import getpath
50
52
InstagramAccountNoFollowError ,
51
53
InstagramPrivateAccountError ,
52
54
)
53
- from minet .instagram .formatters import (
54
- format_comment ,
55
- format_hashtag_post ,
56
- format_post ,
57
- format_user ,
58
- format_user_info ,
55
+ from minet .instagram .types import (
56
+ InstagramComment ,
57
+ InstagramHashtagPost ,
58
+ InstagramPost ,
59
+ InstagramUser ,
60
+ InstagramUserInfo ,
59
61
)
60
62
61
63
INSTAGRAM_GRAPHQL_ENDPOINT = "https://www.instagram.com/graphql/query/"
@@ -216,9 +218,10 @@ def __init__(self, cookie="firefox"):
216
218
217
219
@retrying_method ()
218
220
def request_json (self , url , magic_token = False ):
219
- headers = {"Cookie" : self .cookie }
221
+ headers : Dict [ str , str ] = {"Cookie" : self .cookie }
220
222
221
223
if magic_token :
224
+ assert self .magic_token is not None
222
225
headers ["X-IG-App-ID" ] = self .magic_token
223
226
224
227
response = request (
@@ -290,7 +293,7 @@ def get_magic_token(self):
290
293
return self .magic_token
291
294
292
295
@ensure_magic_token
293
- def comments (self , post ):
296
+ def comments (self , post ) -> Iterator [ InstagramComment ] :
294
297
if not INSTAGRAM_ID_PATTERN .match (post ):
295
298
parsed = parse_instagram_url (post )
296
299
if isinstance (parsed , (ParsedInstagramPost , ParsedInstagramReel )):
@@ -341,7 +344,7 @@ def comments(self, post):
341
344
342
345
already_seen .add (item ["pk" ])
343
346
344
- yield format_comment (item )
347
+ yield InstagramComment . from_payload (item )
345
348
346
349
if item .get ("child_comment_count" ) > 0 :
347
350
max_id = ""
@@ -359,7 +362,7 @@ def comments(self, post):
359
362
children_items = data_comment .get ("child_comments" )
360
363
361
364
for children_item in children_items :
362
- yield format_comment (children_item )
365
+ yield InstagramComment . from_payload (children_item )
363
366
364
367
more_available = data_comment .get (
365
368
"has_more_tail_child_comments"
@@ -375,7 +378,7 @@ def comments(self, post):
375
378
if not min_id :
376
379
break
377
380
378
- def search_hashtag (self , hashtag ):
381
+ def search_hashtag (self , hashtag ) -> Iterator [ InstagramHashtagPost ] :
379
382
hashtag = hashtag .lstrip ("#" )
380
383
cursor = None
381
384
@@ -395,7 +398,7 @@ def search_hashtag(self, hashtag):
395
398
edges = data .get ("edges" )
396
399
397
400
for edge in edges :
398
- yield format_hashtag_post (edge ["node" ])
401
+ yield InstagramHashtagPost . from_payload (edge ["node" ])
399
402
400
403
has_next_page = getpath (data , ["page_info" , "has_next_page" ])
401
404
@@ -405,7 +408,7 @@ def search_hashtag(self, hashtag):
405
408
cursor = getpath (data , ["page_info" , "end_cursor" ])
406
409
407
410
@ensure_magic_token
408
- def post_infos (self , name ):
411
+ def post_infos (self , name ) -> InstagramPost :
409
412
if INSTAGRAM_ID_PATTERN .match (name ):
410
413
url = forge_post_url_from_id (name )
411
414
@@ -427,7 +430,7 @@ def post_infos(self, name):
427
430
if not data :
428
431
raise InstagramInvalidTargetError
429
432
430
- return format_post (getpath (data , ["items" , 0 ]))
433
+ return InstagramPost . from_payload (getpath (data , ["items" , 0 ]))
431
434
432
435
def get_username (self , name ):
433
436
if INSTAGRAM_ID_PATTERN .match (name ):
@@ -464,7 +467,7 @@ def get_user(self, name):
464
467
return self .request_json (url , magic_token = True )
465
468
466
469
@ensure_magic_token
467
- def user_followers (self , name ):
470
+ def user_followers (self , name ) -> Iterator [ InstagramUser ] :
468
471
name = self .get_username (name )
469
472
470
473
max_id = None
@@ -491,15 +494,15 @@ def user_followers(self, name):
491
494
raise InstagramAccountNoFollowError
492
495
493
496
for item in items :
494
- yield format_user (item )
497
+ yield InstagramUser . from_payload (item )
495
498
496
499
max_id = data .get ("next_max_id" )
497
500
498
501
if not max_id :
499
502
break
500
503
501
504
@ensure_magic_token
502
- def user_following (self , name ):
505
+ def user_following (self , name ) -> Iterator [ InstagramUser ] :
503
506
name = self .get_username (name )
504
507
505
508
max_id = None
@@ -526,15 +529,15 @@ def user_following(self, name):
526
529
raise InstagramAccountNoFollowError
527
530
528
531
for item in items :
529
- yield format_user (item )
532
+ yield InstagramUser . from_payload (item )
530
533
531
534
max_id = data .get ("next_max_id" )
532
535
533
536
if not max_id :
534
537
break
535
538
536
539
@ensure_magic_token
537
- def user_posts (self , name ):
540
+ def user_posts (self , name ) -> Iterator [ InstagramPost ] :
538
541
name = self .get_username (name )
539
542
540
543
max_id = None
@@ -562,7 +565,7 @@ def user_posts(self, name):
562
565
raise InstagramPrivateOrNonExistentAccountError
563
566
564
567
for item in items :
565
- yield format_post (item )
568
+ yield InstagramPost . from_payload (item )
566
569
567
570
more_available = data .get ("more_available" )
568
571
@@ -572,7 +575,7 @@ def user_posts(self, name):
572
575
max_id = data .get ("next_max_id" )
573
576
574
577
@ensure_magic_token
575
- def user_infos (self , name ):
578
+ def user_infos (self , name ) -> InstagramUserInfo :
576
579
name = self .get_username (name )
577
580
578
581
data = self .get_user (name )
@@ -585,4 +588,4 @@ def user_infos(self, name):
585
588
if not user :
586
589
raise InstagramInvalidTargetError
587
590
588
- return format_user_info (user )
591
+ return InstagramUserInfo . from_payload (user )
0 commit comments