예제 #1
0
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)
예제 #2
0
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)