3

I have written a simple script to login in TikTok using qrcode, but when I scan it shows that URL is undefined:

from time import sleep
from selenium import webdriver

if __name__ == "__main__":
    driver = webdriver.Chrome(driver_executable_path="path")
    sleep(1)

    driver.get("https://www.tiktok.com")
    sleep(1)

    driver.execute_script(f'document.querySelector("[data-e2e=nav-login-button]").click();')
    sleep(1)
    
    driver.execute_script(f'document.querySelector("a[href*=qrcode]".click();')
    sleep(160)

Result:

undefined?
next_url=undefined%3Fclient_secret%3DQCTI6LYM

Screenshot: https://i.stack.imgur.com/E7qB1.png

AcK
  • 2,063
  • 2
  • 20
  • 27
Dori
  • 175
  • 16
  • it is preferable to use cookies or a user profile so that you can skip the login process, look here https://stackoverflow.com/a/75589648/8157304 – sound wave Mar 16 '23 at 07:56
  • thanks but firstly I need to login and after that I can save and use cookies – Dori Mar 16 '23 at 22:07
  • if you use user profile you can login on the normal chrome browser – sound wave Mar 17 '23 at 08:10
  • In normal chrome browser everything works fine. I want to login using selenium – Dori Mar 17 '23 at 14:43
  • But do you want to login with several accounts or just with one? – sound wave Mar 20 '23 at 08:53
  • How are you scanning the QR code required for login via Chrome using selenium? The website displays this when I manually click login via QR code -- `Log in with QR code` -> ` Open the TikTok app on your mobile device` -> `scan the QR code to confirm your login` – Life is complex Mar 20 '23 at 14:10
  • Yes in this point when I scan the QrCode from TikTok app in mobile, I would except to be logged in Chrome Browser ... but I get just undefined url. Just added screenshot. – Dori Mar 20 '23 at 14:19
  • Look to me like you're getting detected. You might try using [Selenium-Profiles](https://github.com/kaliiiiiiiiii/Selenium-Profiles) or undetected-chromedriver – kaliiiiiiiii Mar 20 '23 at 14:31
  • @dori What happens when you open the Chrome without selenium and try to login using the QR code? – Life is complex Mar 21 '23 at 17:39

2 Answers2

0

There are a couple of things you need to take care:

  • Inducing sleep() without any specific condition to achieve defeats the purpose of Automation and should be avoided at any cost.

  • Instead of invoking execute_script() ideally you need to sync the WebDriver instance with the lagging WebBrowser client. So for the desired clickable element to turn interactable you need to induce WebDriverWait for the element_to_be_clickable().

  • Implementing the above best practices, your effective code block will be:

    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    
    if __name__ == "__main__":
      driver = webdriver.Chrome(
        driver_executable_path="path"
    )
      driver.get("https://www.tiktok.com")
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-e2e=nav-login-button]"))).click()
      WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.CSS_SELECTOR, "a[href*=qrcode]"))).click()
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

Site verify your legitimacy throu your activity, i think it is mouse movement etc.

I have made it work on firefox.

This is function for changing user agent on firefox, but you can use FirefoxOptions in exchange that. I usually use this with custom class so it is reason why self is there but you can use it as standalone function with no trouble.

def change_agent(self:webdriver.Firefox, agent):
    self.get('about:config')
    if self.find_elements(By.CLASS_NAME, 'primary'):
        self.find_element(By.CLASS_NAME, 'primary').click()
    self.find_element('id', 'about-config-search').send_keys('general.useragent.override')
    time.sleep(0.1)
    if self.find_elements(By.CLASS_NAME, 'has-user-value'):
        self.find_element(By.CLASS_NAME, 'has-user-value').find_element(By.TAG_NAME, 'button').click()


    else:
        self.find_element(By.ID, 'prefs').find_element(By.XPATH,
                                                       '/html/body/table/tr/td[1]/form/label[3]/input').click()
        self.find_element(By.ID, 'prefs').find_element(By.TAG_NAME, 'button').click()
    self.find_element(By.TAG_NAME, 'body').send_keys(agent)
    self.find_element(By.CLASS_NAME, 'has-user-value').find_element(By.TAG_NAME, 'button').click()
    return True

Here is some other function to make code more readable:

def decode_img(img_path):
    img = cv2.imread(img_path)
    qcd = cv2.QRCodeDetector()
    url = qcd.detectAndDecode(img)[0]
    return url

def rsleep(f=1, s=3):
    sleep(random.randint(f * 100, s * 100) / 100)


def random_scroll(driver):
    driver.execute_script(
        f"document.documentElement.scrollTop = document.body.scrollTop =    {random.randint(100, 600)}")

To prevent being flagged as boot I have applied random sleep, yeah... it is probably not enough for a reliable solution so it is a good idea to apply additional long mouse click here you have an example how to accomplish that.

if __name__ == "__main__":
    driver = webdriver.Firefox()

    change_agent(driver, "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0")
    driver.get("https://www.tiktok.com")
    rsleep(5, 7)
    # get cookie banner shadowroot
    shadow = driver.execute_script('return arguments[0].shadowRoot.children',
                                   driver.find_element(By.TAG_NAME, 'tiktok-cookie-banner'))
    butt = []
    for el in shadow:
        butt.extend(el.find_elements(By.TAG_NAME, 'button'))
    # allow cookie
    butt[-1].click()

    driver.refresh()


    # few random scrol
    [random_scroll(driver) for x in range(5)]

    driver.execute_script(f'document.querySelector("[data-e2e=nav-login-button]").click();')
    rsleep()

    driver.execute_script(f'document.querySelector("a[href*=qrcode").click();')
    rsleep(3, 4)
    w = driver.find_element(By.CSS_SELECTOR, "div[data-e2e=qr-code]")
    w.screenshot('testqr.png')
    url = decode_img('testqr.png')

At this point you can check for "undefined" in url.

Obviously, because this file is now saved in storage you can run the whole process on remote server and send qrcode through socket/ provide it via flask etc. ps. Probably you need to change user_agent string for it to work

jomal j
  • 15
  • 6