Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Zaytsev Dmitry
committed
Sep 19, 2017
0 parents
commit 50f4936
Showing
6 changed files
with
262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.idea/ | ||
venv/ | ||
liked_posts.txt | ||
*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
MIT License | ||
|
||
Copyright (c) 2017 Zaytsev Dmitriy | ||
https://github.com/dzaytsev91/mygf-instagram | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
## What is it? | ||
|
||
This is instagram bot for liking your girlfriend's instagram posts, just put it script in cron and you don't waste your time checking feed | ||
|
||
Written in python 3 | ||
|
||
## Requirements | ||
`requests` | ||
|
||
## Configurations | ||
|
||
Just call InstagramBot with 3 arguments | ||
`login - your login ` | ||
`password - your password` | ||
`target - Instagram account name of your gf` | ||
|
||
|
||
## How to install and run: | ||
1) Clone this repo | ||
2) Create virtual env | ||
3) To install the project's dependencies, run command `pip install -r requirements.txt` | ||
|
||
## Usage | ||
#### Example of usage: | ||
Just change password, login and target | ||
|
||
`virtualenv -p python3 venv` | ||
`. venv/bin/activate` | ||
`pip install -r requirements.txt` | ||
`python example.py` | ||
|
||
|
||
## Plans | ||
|
||
1) Before starting check if I'm online, if not don't like any post | ||
2) Add possibility to like random images | ||
3) Send me all images that bot liked to messenger that I can check when it will be time for this |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from instagram_bot import InstagramBot | ||
|
||
|
||
def main(): | ||
bot = InstagramBot( | ||
login='login', password='password', target='account_name_of_your_gf' | ||
) | ||
bot.like_all_users_media() | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
import time | ||
import requests | ||
import datetime | ||
import json | ||
import logging | ||
import random | ||
|
||
|
||
class InstagramBot(object): | ||
""" | ||
Created on base of https://github.com/LevPasha/instabot.py | ||
""" | ||
|
||
url = 'https://www.instagram.com/' | ||
url_likes = 'https://www.instagram.com/web/likes/%s/like/' | ||
url_login = 'https://www.instagram.com/accounts/login/ajax/' | ||
url_logout = 'https://www.instagram.com/accounts/logout/' | ||
url_media_detail = 'https://www.instagram.com/p/%s/?__a=1' | ||
url_user_detail = 'https://www.instagram.com/%s/?__a=1' | ||
|
||
user_agent = ("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 " | ||
"(KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36") | ||
accept_language = 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4' | ||
|
||
log_file_path = '' | ||
log_file = 0 | ||
|
||
def __init__(self, login, password, target, log_to_file=False): | ||
|
||
self.bot_start = datetime.datetime.now() | ||
|
||
self.user_login = login.lower() | ||
self.user_password = password | ||
self.target = target | ||
self.login_status = False | ||
self.login_post = None | ||
self.csrftoken = None | ||
self.log_to_file = log_to_file | ||
self.s = requests.Session() | ||
now_time = datetime.datetime.now() | ||
log_string = 'InstagramBot started at %s:\n' % \ | ||
(now_time.strftime("%d.%m.%Y %H:%M")) | ||
|
||
if self.log_to_file: | ||
log_full_path = '%s%s.log' % ( | ||
self.log_file_path, self.user_login) | ||
formatter = logging.Formatter('%(asctime)s - %(name)s ' | ||
'- %(message)s') | ||
self.logger = logging.getLogger(self.user_login) | ||
hdrl = logging.FileHandler(log_full_path, mode='w') | ||
hdrl.setFormatter(formatter) | ||
self.logger.setLevel(level=logging.INFO) | ||
self.logger.addHandler(hdrl) | ||
self.write_log(log_string) | ||
|
||
def login(self): | ||
log_string = 'Trying to login as %s...\n' % self.user_login | ||
self.write_log(log_string) | ||
self.s.cookies.update({ | ||
'sessionid': '', | ||
'mid': '', | ||
'ig_pr': '1', | ||
'ig_vw': '1920', | ||
'csrftoken': '', | ||
's_network': '', | ||
'ds_user_id': '' | ||
}) | ||
self.login_post = { | ||
'username': self.user_login, | ||
'password': self.user_password | ||
} | ||
self.s.headers.update({ | ||
'Accept-Encoding': 'gzip, deflate', | ||
'Accept-Language': self.accept_language, | ||
'Connection': 'keep-alive', | ||
'Content-Length': '0', | ||
'Host': 'www.instagram.com', | ||
'Origin': 'https://www.instagram.com', | ||
'Referer': 'https://www.instagram.com/', | ||
'User-Agent': self.user_agent, | ||
'X-Instagram-AJAX': '1', | ||
'X-Requested-With': 'XMLHttpRequest' | ||
}) | ||
r = self.s.get(self.url) | ||
self.s.headers.update({'X-CSRFToken': r.cookies['csrftoken']}) | ||
time.sleep(5 * random.random()) | ||
login = self.s.post( | ||
self.url_login, data=self.login_post, allow_redirects=True) | ||
self.s.headers.update({'X-CSRFToken': login.cookies['csrftoken']}) | ||
self.csrftoken = login.cookies['csrftoken'] | ||
time.sleep(5 * random.random()) | ||
|
||
if login.status_code == 200: | ||
r = self.s.get('https://www.instagram.com/') | ||
finder = r.text.find(self.user_login) | ||
if finder != -1: | ||
self.login_status = True | ||
log_string = '%s login success!' % self.user_login | ||
self.write_log(log_string) | ||
else: | ||
self.login_status = False | ||
self.write_log('Login error! Check your login data!') | ||
else: | ||
self.write_log('Login error! Connection error!') | ||
|
||
def logout(self): | ||
work_time = datetime.datetime.now() - self.bot_start | ||
log_string = 'Bot work time: %s' % work_time | ||
self.write_log(log_string) | ||
|
||
try: | ||
logout_post = {'csrfmiddlewaretoken': self.csrftoken} | ||
self.s.post(self.url_logout, data=logout_post) | ||
self.write_log("Logout success!") | ||
self.login_status = False | ||
except Exception as e: | ||
self.write_log("Logout error! %s" % e) | ||
|
||
def like_all_users_media(self): | ||
""" Send http request to like target's feed """ | ||
feed_url = self.url_user_detail % self.target | ||
try: | ||
response = self.s.get(feed_url) | ||
users_feed = json.loads(response.text) | ||
with open("liked_posts.txt", 'r') as f: | ||
already_liked_nodes = f.read().splitlines() | ||
with open("liked_posts.txt", 'a') as f: | ||
for media in users_feed['user']['media']['nodes']: | ||
if media['id'] not in already_liked_nodes: | ||
if not self.login_status: | ||
self.login() | ||
|
||
media = self.s.get(self.url_media_detail % media['code']) | ||
if media.status_code != 200: | ||
self.write_log("Media request returned %d status code" | ||
% media.status_code) | ||
continue | ||
media_data = json.loads(media.text) | ||
media_info = media_data['graphql']['shortcode_media'] | ||
if not media_info['viewer_has_liked']: | ||
self.like(media_info['id']) | ||
sleep_time = random.randint(5, 15) | ||
self.write_log("Sleeping %d" % sleep_time) | ||
time.sleep(sleep_time) | ||
f.write(media_info['id'] + '\n') | ||
except Exception as e: | ||
self.write_log("An error occurred %s" % e) | ||
if self.login_status: | ||
self.logout() | ||
return | ||
|
||
def like(self, media_id): | ||
""" Send http request to like media by ID """ | ||
if self.login_status: | ||
url_likes = self.url_likes % media_id | ||
try: | ||
res = self.s.post(url_likes) | ||
if res.status_code != 200: | ||
if res.status_code == 400: | ||
# in case you get banned sleep 5 minutes | ||
time.sleep(60 * 5) | ||
res = self.s.post(url_likes) | ||
if res.status_code != 200: | ||
self.write_log("Except on like! Status code %d" | ||
% res.status_code) | ||
return | ||
self.write_log('Successfully liked %s' % media_id) | ||
|
||
except Exception as e: | ||
self.write_log("Except on like! %s" % e) | ||
return | ||
|
||
def write_log(self, log_text): | ||
if self.log_to_file: | ||
try: | ||
self.logger.info(log_text) | ||
except UnicodeEncodeError: | ||
print("Your text has unicode problem!") | ||
else: | ||
try: | ||
print(log_text) | ||
except UnicodeEncodeError: | ||
print("Your text has unicode problem!") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
requests==2.18.4 |