class Instagram(): """ Instagram 操作用 Class """ def __init__(self, browser): self.browser = browser self.count = 0 self.now = datetime.now().strftime('%Y%m%d%H%M%S') self.cookie_jar = RequestsCookieJar() def screenshot(self): """ Screenshot を撮って /tmp に保存する """ _path = '/tmp/%s-instagram-screenshot-%03d.png' % (self.now, self.count) _log('info', 'Save screenshot to %s' % _path) self.browser.driver.save_screenshot(_path) self.count += 1 def login(self, username, password): """ Instagram への Login 処理 """ self.browser.visit('https://www.instagram.com/') sleep(2) # Input _elements = self.browser.find_by_tag('input') if len(_elements) < 2: _log('fatal', 'Input form for login does not exist') return False _elements.first.fill(username) _elements.last.fill(password) # Button _elements = self.browser.find_by_css('button[type=submit]') if len(_elements) < 1: _log('fatal', 'Submit button for login does not exist') return False _elements.first.click() # checking to move page if not self._wait_to_set_cookie('sessionid', 5): _log('error', 'Failed to login') return False if self.browser.url == 'https://www.instagram.com/accounts/onetap/?next=%2F': if not self._save_login_info(): _log('fatal', 'Failed to save login info') return False self._update_cookies() if self.browser.url.startswith('https://www.instagram.com/challenge'): if not self._send_security_code(): _log('error', 'Failed to authenticate by security code') return False return True def get_users(self, keyword): """ Instagram の User 情報を取得する """ _params = { 'context': 'user', 'query': keyword, 'rank_token': random(), 'include_reel': 'false'} _log('debug', 'Search User: %s' % keyword) _result = requests.get( 'https://www.instagram.com/web/search/topsearch/', params=_params, cookies=self.cookie_jar) if _result.status_code != 200: _log('error', 'Failed to get users.') return None try: return json.loads(_result.text) except json.decoder.JSONDecodeError as error: _log('fatal', _result.text) self.screenshot() raise error def follow_user(self, username): """ 指定した User を Follow する """ _log('info', 'Try to follow user is %s' % username) _url = 'https://www.instagram.com/%s/' % username self.browser.visit(_url) sleep(2) if self.browser.url != _url: _log('error', 'Failed to move user page to %s' % _url) return False _elements = self.browser.find_by_css('main header button') if len(_elements) == 0: _log('fatal', 'Follow button does not exist in %s' % _url) return False _text = _elements.first.outer_html _elements.first.click() sleep(1) _elements = self.browser.find_by_css('main header button') if _text == _elements.first.outer_html: _log('error', 'Failed to follow user: %s' % username) return True def _save_login_info(self): _url = self.browser.url _elements = self.browser.find_by_css('button[type=button]') if len(_elements) == 0: _log('fatal', 'To save login info button does not exist') return False _elements.first.click() return self._wait_to_move_page(_url, 5) def _send_security_code(self): _elements = self.browser.find_by_css('button') if len(_elements) == 0: _log('fatal', 'To send security code button does not exist') return False _elements.last.click() sleep(2) _elements = self.browser.find_by_css('input[name=security_code]') if len(_elements) == 0: _log('fatal', 'Input form for security code does not exist') return False _security_code = input('Input Serucity Code > ') _elements.first.fill(_security_code) _elements = self.browser.find_by_tag('button') if len(_elements) == 0: _log('fatal', 'To submit security code button code does not exist') return False _url = self.browser.url _log('debug', 'challenge page: %s' % _url) _elements.first.click() return self._wait_to_move_page(_url, 5) def _wait_to_move_page(self, url, trials): for _ in range(trials): sleep(1) if self.browser.url != url: return True return False def _wait_to_set_cookie(self, cookie_name, trials): for _ in range(trials): sleep(1) if self.browser.driver.get_cookie(cookie_name) is not None: return True return False def _update_cookies(self): self.cookie_jar.clear() for cookie in self.browser.driver.get_cookies(): _options = {} if 'domain' in cookie: _options['domain'] = cookie['domain'] if 'expire' in cookie: _options['expires'] = cookie['expire'] if 'httpOnly' in cookie and cookie['httpOnly']: _options['rest'] = {'HttpOnly': True} if 'path' in cookie: _options['path'] = cookie['path'] if 'secure' in cookie and cookie['secure']: _options['secure'] = True self.cookie_jar.set(cookie['name'], cookie['value'], **_options)
class Account: headers = c.headers data = None proxies = c.proxies def __init__(self, email, password=None, cookie=None): self.email = email self.cookies = RequestsCookieJar() if password is None: temp_cookie = SimpleCookie() temp_cookie.load(cookie) for key, morsel in temp_cookie.items(): self.cookies[key] = morsel.value self.cookie = True else: self.password = password self.cookie = False def login(self, mobile=False, useProxy=False): self.headers = c.headers if not self.cookie: postURL = self.preLogin(useProxy=useProxy) res = self.post(postURL, data=self.data, useProxy=useProxy) # Parse HTML Form form = BeautifulSoup(res.text, "html.parser").findAll("form")[0] # Get Form params = dict() for field in form: # Add each field to params params[field["name"]] = field["value"] self.headers["Host"] = c.host # Set Host to Bing Server self.cookies.clear() res = self.post(form.get("action"), data=params, useProxy=useProxy) if mobile: self.headers = c.mobileHeaders def preLogin(self, useProxy=False): res = self.get(c.hostURL, useProxy=useProxy) # Get Login URL index = res.text.index("WindowsLiveId") # Find URL cutText = res.text[index + 16:] # Cut Text at Start of URL loginURL = cutText[:cutText.index("\"")] # Cut at End of URL # Unescape URL loginURL = bytes(loginURL, encoding="UTF-8").decode("unicode_escape") # Get Login Cookies self.headers["Host"] = c.loginHost # Set Host to Login Server res = self.get(loginURL, useProxy=useProxy) self.data = self.getAuthData() self.cookies["CkTst"] = "G" + \ str(int(time.time() * 1000)) # Add Time Cookie # Get Post URL index = res.text.index(c.loginPostURL) # Find URL cutText = res.text[index:] # Cut Text at Start of URL postURL = cutText[:cutText.index("\'")] # Cut at End of URL # Get PPFT index = res.text.index("sFTTag") # Find PPFT cutText = res.text[index:] # Cut Text Near PPFT PPFT = cutText[cutText.index("value=") + 7:cutText.index("\"/>")] # Cut PPFT self.data["PPFT"] = PPFT # Get PPSX index = res.text.index(",bH:\'") # Find PPSX cutText = res.text[index + 4:] # Cut Text at Start of PPSX PPSX = cutText[:cutText.index("\'")] # Cut at End of PPSX self.data["PPSX"] = PPSX # Finish Up self.cookies["wlidperf"] = "FR=L&ST=" + \ str(int(time.time() * 1000)) # Add Another Time Cookie return postURL def logout(self): if not self.cookie: self.cookies.clear() def getAuthData(self): return { "login": self.email, "loginfmt": self.email, "passwd": self.password, "i13": "0", "type": "11", "LoginOptions": "3", "lrt": "", "ps": "2", "psRNGCDefaultType": "", "psRNGCEntropy": "", "psRNGCSLK": "", "canary": "", "ctx": "", "NewUser": "******", "FoundMSAs": "", "fspost": "0", "i21": "0", "i2": "1", "i17": "0", "i18": "__ConvergedLoginPaginatedStrings%7C1%2C__ConvergedLogin_PCore%7C1%2C", "i19": "2" + str(randint(0, 5000)) } def request(self, method, URL, headers=USE_SELF, cookies=USE_SELF, params=None, data=None, proxies=USE_SELF, useProxy=False, setReferer=True, setCookies=True): headers = self.headers if headers is USE_SELF else headers cookies = self.cookies if cookies is USE_SELF else cookies proxies = self.proxies if proxies is USE_SELF else proxies res = requests.request(method, URL, headers=headers, cookies=cookies, params=params, data=data, proxies=proxies if useProxy else None) if setReferer: self.headers["Referer"] = URL if setCookies: self.cookies.update(res.cookies) return res def get(self, URL, headers=USE_SELF, cookies=USE_SELF, params=None, data=None, proxies=USE_SELF, useProxy=False, setReferer=True, setCookies=True): return self.request('GET', URL, headers, cookies, params, data, proxies, useProxy, setReferer, setCookies) def post(self, URL, headers=USE_SELF, cookies=USE_SELF, params=None, data=None, proxies=USE_SELF, useProxy=False, setReferer=True, setCookies=True): return self.request('POST', URL, headers, cookies, params, data, proxies, useProxy, setReferer, setCookies)