mirror of
https://github.com/instaloader/instaloader.git
synced 2026-10-23 17:09:37 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9648bc551 | ||
|
|
6d90c47d9a | ||
|
|
1c577716dd | ||
|
|
6824d7b75c | ||
|
|
6ad03d3575 | ||
|
|
03ac067e71 | ||
|
|
e70faf506d | ||
|
|
cc2986cff3 | ||
|
|
c7372e36cc | ||
|
|
74f7970b50 | ||
|
|
f4ecfea64c | ||
|
|
0586a1fec3 | ||
|
|
c53625028d |
@@ -6,3 +6,4 @@ Instaloader is written by
|
|||||||
- Alexander Graf (@aandergr)
|
- Alexander Graf (@aandergr)
|
||||||
- André Koch-Kramer (@Thammus)
|
- André Koch-Kramer (@Thammus)
|
||||||
- Lars Lindqvist (@e5150)
|
- Lars Lindqvist (@e5150)
|
||||||
|
- ... and many more, see https://github.com/instaloader/instaloader/graphs/contributors
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement by opening an
|
||||||
|
issue or contacting one or more of the project maintainers.
|
||||||
|
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
|
||||||
|
at [https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2016-2019 Alexander Graf and André Koch-Kramer.
|
Copyright (c) 2016-2020 Alexander Graf and André Koch-Kramer.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ To **upgrade Instaloader** to its current version, do::
|
|||||||
- On **Windows 10**, you may download the standalone executable from the
|
- On **Windows 10**, you may download the standalone executable from the
|
||||||
`current release page <https://github.com/instaloader/instaloader/releases/latest>`__.
|
`current release page <https://github.com/instaloader/instaloader/releases/latest>`__.
|
||||||
|
|
||||||
|
- On **Android**, you can use Instaloader with `Termux <https://play.google.com/store/apps/details?id=com.termux>`__
|
||||||
|
after typing ``pkg install python`` and ``pip3 install instaloader``.
|
||||||
|
|
||||||
- To test the most current **pre-release** version of Instaloader::
|
- To test the most current **pre-release** version of Instaloader::
|
||||||
|
|
||||||
pip3 install --pre instaloader
|
pip3 install --pre instaloader
|
||||||
|
|||||||
+17
-10
@@ -9,10 +9,7 @@ Troubleshooting
|
|||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Instaloader has a logic to keep track of its requests to Instagram and to obey
|
Instaloader has a logic to keep track of its requests to Instagram and to obey
|
||||||
their rate limits. Since they are nowhere documented, we try them out
|
their rate limits. The rate controller assumes that
|
||||||
experimentally. We have a daily cron job running to confirm that Instaloader
|
|
||||||
still stays within the rate limits. Nevertheless, the rate control logic assumes
|
|
||||||
that
|
|
||||||
|
|
||||||
- at one time, Instaloader is the only application that consumes requests, i.e.
|
- at one time, Instaloader is the only application that consumes requests, i.e.
|
||||||
neither the Instagram browser interface, nor a mobile app, nor another
|
neither the Instagram browser interface, nor a mobile app, nor another
|
||||||
@@ -21,7 +18,13 @@ that
|
|||||||
- no requests had been consumed when Instaloader starts.
|
- no requests had been consumed when Instaloader starts.
|
||||||
|
|
||||||
The latter one implies that restarting or reinstantiating Instaloader often
|
The latter one implies that restarting or reinstantiating Instaloader often
|
||||||
within short time is prone to cause a 429. If a request is denied with a 429,
|
within short time is prone to cause a 429.
|
||||||
|
|
||||||
|
Since the behavior of the rate controller might change between different
|
||||||
|
versions of Instaloader, make sure to use the current version of Instaloader,
|
||||||
|
especially when encountering many 429 errors.
|
||||||
|
|
||||||
|
If a request is denied with a 429,
|
||||||
Instaloader retries the request as soon as the temporary ban is assumed to be
|
Instaloader retries the request as soon as the temporary ban is assumed to be
|
||||||
expired. In case the retry continuously fails for some reason, which should not
|
expired. In case the retry continuously fails for some reason, which should not
|
||||||
happen under normal conditions, consider adjusting the
|
happen under normal conditions, consider adjusting the
|
||||||
@@ -32,13 +35,18 @@ promiscuous IP addresses, such as cloud, VPN and public proxy services, might be
|
|||||||
subject to significantly stricter limits for anonymous access. However,
|
subject to significantly stricter limits for anonymous access. However,
|
||||||
logged-in accesses (see :option:`--login`) do not seem to be affected.
|
logged-in accesses (see :option:`--login`) do not seem to be affected.
|
||||||
|
|
||||||
|
Instaloader allows to adjust the rate controlling behavior by overriding
|
||||||
|
:class:`instaloader.RateController`.
|
||||||
|
|
||||||
Too many queries in the last time
|
Too many queries in the last time
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
**"Too many queries in the last time"** is not an error. It is a notice that the
|
**"Too many queries in the last time"** is not an error. It is a notice that the
|
||||||
rate limit has almost been reached, according to Instaloader's own rate
|
rate limit has almost been reached, according to Instaloader's own rate
|
||||||
accounting mechanism. We regularly adjust this mechanism to match Instagram's
|
accounting mechanism.
|
||||||
current rate limiting.
|
|
||||||
|
Instaloader allows to adjust the rate controlling behavior by overriding
|
||||||
|
:class:`instaloader.RateController`.
|
||||||
|
|
||||||
Private but not followed
|
Private but not followed
|
||||||
------------------------
|
------------------------
|
||||||
@@ -57,9 +65,8 @@ pointing the user to an URL to be opened in a browser.
|
|||||||
Nevertheless, in :issue:`92` and :issue:`615` users reported problems with
|
Nevertheless, in :issue:`92` and :issue:`615` users reported problems with
|
||||||
logging in. We recommend to always keep the session file which Instaloader
|
logging in. We recommend to always keep the session file which Instaloader
|
||||||
creates when using :option:`--login`. If a session file is present,
|
creates when using :option:`--login`. If a session file is present,
|
||||||
:option:`--login` does not make make use of the failure-prone login procedure.
|
:option:`--login` does not make use of the failure-prone login procedure.
|
||||||
Also, session files usually do not expire and can be copied between different
|
Also, session files usually do not expire.
|
||||||
computers without any problems.
|
|
||||||
|
|
||||||
If you do not have a session file present, you may use the following script
|
If you do not have a session file present, you may use the following script
|
||||||
(:example:`615_import_firefox_session.py`) to workaround login problems by
|
(:example:`615_import_firefox_session.py`) to workaround login problems by
|
||||||
|
|||||||
@@ -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.5.3'
|
__version__ = '4.5.4'
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -579,12 +579,12 @@ class Instaloader:
|
|||||||
|
|
||||||
def _userid_chunks():
|
def _userid_chunks():
|
||||||
assert userids is not None
|
assert userids is not None
|
||||||
userids_per_query = 100
|
userids_per_query = 50
|
||||||
for i in range(0, len(userids), userids_per_query):
|
for i in range(0, len(userids), userids_per_query):
|
||||||
yield userids[i:i + userids_per_query]
|
yield userids[i:i + userids_per_query]
|
||||||
|
|
||||||
for userid_chunk in _userid_chunks():
|
for userid_chunk in _userid_chunks():
|
||||||
stories = self.context.graphql_query("bf41e22b1c4ba4c9f31b844ebb7d9056",
|
stories = self.context.graphql_query("303a4ae99711322310f25250d988f3b7",
|
||||||
{"reel_ids": userid_chunk, "precomposed_overlay": False})["data"]
|
{"reel_ids": userid_chunk, "precomposed_overlay": False})["data"]
|
||||||
yield from (Story(self.context, media) for media in stories['reels_media'])
|
yield from (Story(self.context, media) for media in stories['reels_media'])
|
||||||
|
|
||||||
|
|||||||
@@ -147,10 +147,6 @@ class Post:
|
|||||||
)
|
)
|
||||||
self._full_metadata_dict = pic_json['data']['shortcode_media']
|
self._full_metadata_dict = pic_json['data']['shortcode_media']
|
||||||
if self._full_metadata_dict is None:
|
if self._full_metadata_dict is None:
|
||||||
# issue #449
|
|
||||||
self._context.error("Fetching Post metadata failed (issue #449). "
|
|
||||||
"The following data has been returned:\n"
|
|
||||||
+ json.dumps(pic_json['entry_data'], indent=2))
|
|
||||||
raise BadResponseException("Fetching Post metadata failed.")
|
raise BadResponseException("Fetching Post metadata failed.")
|
||||||
if self.shortcode != self._full_metadata_dict['shortcode']:
|
if self.shortcode != self._full_metadata_dict['shortcode']:
|
||||||
self._node.update(self._full_metadata_dict)
|
self._node.update(self._full_metadata_dict)
|
||||||
@@ -207,7 +203,13 @@ class Post:
|
|||||||
@property
|
@property
|
||||||
def owner_id(self) -> int:
|
def owner_id(self) -> int:
|
||||||
"""The ID of the Post's owner."""
|
"""The ID of the Post's owner."""
|
||||||
return self.owner_profile.userid
|
# The ID may already be available, e.g. if the post instance was created
|
||||||
|
# from an `hashtag.get_posts()` iterator, so no need to make another
|
||||||
|
# http request.
|
||||||
|
if 'owner' in self._node and 'id' in self._node['owner']:
|
||||||
|
return self._node['owner']['id']
|
||||||
|
else:
|
||||||
|
return self.owner_profile.userid
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def date_local(self) -> datetime:
|
def date_local(self) -> datetime:
|
||||||
@@ -435,7 +437,14 @@ class Post:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_likes(self) -> Iterator['Profile']:
|
def get_likes(self) -> Iterator['Profile']:
|
||||||
"""Iterate over all likes of the post. A :class:`Profile` instance of each likee is yielded."""
|
"""
|
||||||
|
Iterate over all likes of the post. A :class:`Profile` instance of each likee is yielded.
|
||||||
|
|
||||||
|
.. versionchanged:: 4.5.4
|
||||||
|
Require being logged in (as required by Instagram).
|
||||||
|
"""
|
||||||
|
if not self._context.is_logged_in:
|
||||||
|
raise LoginRequiredException("--login required to access likes of a post.")
|
||||||
if self.likes == 0:
|
if self.likes == 0:
|
||||||
# Avoid doing additional requests if there are no comments
|
# Avoid doing additional requests if there are no comments
|
||||||
return
|
return
|
||||||
@@ -1350,9 +1359,13 @@ class Hashtag:
|
|||||||
next_other = next(other_posts, None)
|
next_other = next(other_posts, None)
|
||||||
while next_top is not None or next_other is not None:
|
while next_top is not None or next_other is not None:
|
||||||
if next_other is None:
|
if next_other is None:
|
||||||
|
assert next_top is not None
|
||||||
|
yield next_top
|
||||||
yield from sorted_top_posts
|
yield from sorted_top_posts
|
||||||
break
|
break
|
||||||
if next_top is None:
|
if next_top is None:
|
||||||
|
assert next_other is not None
|
||||||
|
yield next_other
|
||||||
yield from other_posts
|
yield from other_posts
|
||||||
break
|
break
|
||||||
if next_top == next_other:
|
if next_top == next_other:
|
||||||
|
|||||||
Reference in New Issue
Block a user