mirror of
https://github.com/instaloader/instaloader.git
synced 2026-11-03 14:05:49 -08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebdc5f1557 | ||
|
|
4c6a184390 | ||
|
|
ed9ca62a48 | ||
|
|
99c3960ad4 | ||
|
|
14124b617e | ||
|
|
b40a5aa243 | ||
|
|
cc8c9ff883 |
@@ -124,6 +124,7 @@ Supporters
|
|||||||
.. current-sponsors-start
|
.. current-sponsors-start
|
||||||
|
|
||||||
| Instaloader is proudly sponsored by
|
| Instaloader is proudly sponsored by
|
||||||
|
| `@rocketapi-io <https://github.com/rocketapi-io>`__
|
||||||
| `@socialmethod <https://github.com/socialmethod>`__
|
| `@socialmethod <https://github.com/socialmethod>`__
|
||||||
|
|
||||||
See `Alex' GitHub Sponsors <https://github.com/sponsors/aandergr>`__ page for
|
See `Alex' GitHub Sponsors <https://github.com/sponsors/aandergr>`__ page for
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""Download pictures (or videos) along with their captions and other metadata from Instagram."""
|
"""Download pictures (or videos) along with their captions and other metadata from Instagram."""
|
||||||
|
|
||||||
|
|
||||||
__version__ = '4.10b1'
|
__version__ = '4.10'
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -372,8 +372,11 @@ class InstaloaderContext:
|
|||||||
resp = sess.get('https://{0}/{1}'.format(host, path), params=params, allow_redirects=False)
|
resp = sess.get('https://{0}/{1}'.format(host, path), params=params, allow_redirects=False)
|
||||||
if resp.status_code in self.fatal_status_codes:
|
if resp.status_code in self.fatal_status_codes:
|
||||||
redirect = " redirect to {}".format(resp.headers['location']) if 'location' in resp.headers else ""
|
redirect = " redirect to {}".format(resp.headers['location']) if 'location' in resp.headers else ""
|
||||||
raise AbortDownloadException("Query to https://{}/{} responded with \"{} {}\"{}".format(
|
body = ""
|
||||||
host, path, resp.status_code, resp.reason, redirect
|
if resp.headers['Content-Type'].startswith('application/json'):
|
||||||
|
body = ': ' + resp.text[:500] + ('…' if len(resp.text) > 501 else '')
|
||||||
|
raise AbortDownloadException("Query to https://{}/{} responded with \"{} {}\"{}{}".format(
|
||||||
|
host, path, resp.status_code, resp.reason, redirect, body
|
||||||
))
|
))
|
||||||
while resp.is_redirect:
|
while resp.is_redirect:
|
||||||
redirect_url = resp.headers['location']
|
redirect_url = resp.headers['location']
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class NodeIterator(Iterator[T]):
|
|||||||
if self._first_node is None:
|
if self._first_node is None:
|
||||||
self._first_node = node
|
self._first_node = node
|
||||||
return item
|
return item
|
||||||
if self._data['page_info']['has_next_page']:
|
if self._data.get('page_info', {}).get('has_next_page'):
|
||||||
query_response = self._query(self._data['page_info']['end_cursor'])
|
query_response = self._query(self._data['page_info']['end_cursor'])
|
||||||
if self._data['edges'] != query_response['edges'] and len(query_response['edges']) > 0:
|
if self._data['edges'] != query_response['edges'] and len(query_response['edges']) > 0:
|
||||||
page_index, data = self._page_index, self._data
|
page_index, data = self._page_index, self._data
|
||||||
@@ -289,7 +289,7 @@ def resumable_iteration(context: InstaloaderContext,
|
|||||||
is_resuming = True
|
is_resuming = True
|
||||||
start_index = iterator.total_index
|
start_index = iterator.total_index
|
||||||
context.log("Resuming from {}.".format(resume_file_path))
|
context.log("Resuming from {}.".format(resume_file_path))
|
||||||
except (InvalidArgumentException, LZMAError, json.decoder.JSONDecodeError) as exc:
|
except (InvalidArgumentException, LZMAError, json.decoder.JSONDecodeError, EOFError) as exc:
|
||||||
context.error("Warning: Not resuming from {}: {}".format(resume_file_path, exc))
|
context.error("Warning: Not resuming from {}: {}".format(resume_file_path, exc))
|
||||||
try:
|
try:
|
||||||
yield is_resuming, start_index
|
yield is_resuming, start_index
|
||||||
|
|||||||
@@ -1097,6 +1097,27 @@ class Profile:
|
|||||||
def _make_is_newest_checker() -> Callable[[Post, Optional[Post]], bool]:
|
def _make_is_newest_checker() -> Callable[[Post, Optional[Post]], bool]:
|
||||||
return lambda post, first: first is None or post.date_local > first.date_local
|
return lambda post, first: first is None or post.date_local > first.date_local
|
||||||
|
|
||||||
|
def get_followed_hashtags(self) -> NodeIterator['Hashtag']:
|
||||||
|
"""
|
||||||
|
Retrieve list of hashtags followed by given profile.
|
||||||
|
To use this, one needs to be logged in and private profiles has to be followed.
|
||||||
|
|
||||||
|
:rtype: NodeIterator[Hashtag]
|
||||||
|
|
||||||
|
.. versionadded:: 4.10
|
||||||
|
"""
|
||||||
|
if not self._context.is_logged_in:
|
||||||
|
raise LoginRequiredException("--login required to get a profile's followers.")
|
||||||
|
self._obtain_metadata()
|
||||||
|
return NodeIterator(
|
||||||
|
self._context,
|
||||||
|
'e6306cc3dbe69d6a82ef8b5f8654c50b',
|
||||||
|
lambda d: d["data"]["user"]["edge_following_hashtag"],
|
||||||
|
lambda n: Hashtag(self._context, n),
|
||||||
|
{'id': str(self.userid)},
|
||||||
|
'https://www.instagram.com/{0}/'.format(self.username),
|
||||||
|
)
|
||||||
|
|
||||||
def get_followers(self) -> NodeIterator['Profile']:
|
def get_followers(self) -> NodeIterator['Profile']:
|
||||||
"""
|
"""
|
||||||
Retrieve list of followers of given profile.
|
Retrieve list of followers of given profile.
|
||||||
|
|||||||
Reference in New Issue
Block a user