如何通过代码/API调用或不登录浏览器来为用户生成_forum_session和_t?

我写了一段使用 Selenium 和 Python 生成 Cookie (_forum_session 和 _t) 的代码。但在这种情况下,我们仍然需要手动填写电话号码和 OTP 进行验证。我想通过代码完全自动生成 Cookie,不想手动填写任何内容。如何实现?

您能退一步描述一下拥有这些 Cookie 将解决什么问题?

您想完成什么?您是想让 Discourse 针对您的应用程序进行身份验证吗?也许可以看看 DiscourseConnect - Discourse 的官方单点登录 (sso)

我通过 generate_cookies.py 获得了 cookies.pkl,我每 5 分钟使用它来自动测试登录。

因此,我有一个 login_12.py 文件,每 5 分钟调用一次来测试我的登录
login_12.py (下面是一些代码示例)

import cookies.pkl
driver.get("https://forum.discourse.org/")
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
    logger.debug(jlog.format(timestamp=datetime.now(), level="DEBUG", status="Executing", message="Homepage reloaded"))
    time.sleep(3)

    cookies = pickle.load(open("cookies.pkl", "rb"))
    for cookie in cookies:
        print(cookie)
        driver.add_cookie(cookie)
    logger.debug(jlog.format(timestamp=datetime.now(), level="DEBUG", status="Executing", message="Added cookies"))
    time.sleep(2)

    driver.get(driver.current_url)
        logger.debug(jlog.format(timestamp=datetime.now(), level="DEBUG", status="Executing", message="Homepage reloaded"))

我想在不使用浏览器的情况下自动生成 cookie,以便整个过程是自动的。

你仍然在描述你提出的解决方案,而不是你试图解决的问题。

如果你不需要浏览器,为什么还需要 Cookie?

你是否想让你的外部应用程序能够对 Discourse 执行某些操作?也许只使用 API 密钥?

1 个赞

为什么需要 cookie?
答:因为如果不添加 cookies.pkl 文件,我们就无法通过 login_12.py 文件登录。

目前,要生成 cookie,我们必须在 Chrome 驱动浏览器中手动填写电话号码和 OTP。我不想手动填写任何内容,这就是为什么我不想使用浏览器来生成 cookie。

generate_cookies.py(示例代码)

from selenium import webdriver
import undetected_chromedriver as uc

options = uc.ChromeOptions()
#options.add_argument('--headless')
options.add_argument("--disable-extensions")
options.add_argument("--disable-popup-blocking")

# 登录
GMAIL = 'discourse.mytest@ymail.com'
PASSWORD = 'test1234'

driver.get("https://forun.discourse.org/")
print(driver.title)
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
print('Homepage loaded')


WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, 'login-button')))
login = driver.find_elements_by_class_name("login-button")[0]
print(login)
login.send_keys(Keys.RETURN)
print(driver.current_url)
driver.get(driver.current_url)
print("email")
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
print('Email page loaded')
#print(driver.page_source)

driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input").send_keys(GMAIL)
driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input").send_keys(Keys.RETURN)
print("Email entered")

time.sleep(3)

WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
print('Password page loaded')
#print(driver.page_source)

driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input").send_keys(PASSWORD)
driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input").send_keys(Keys.RETURN)
print("Password entered")
time.sleep(3)

WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
print('Login completed')
print(driver.title)

#print(driver.find_element_by_xpath("/html/body").get_attribute('innerHTML'))

if not "Discourse Forum" in driver.title:
    raise Exception('login Error')
else:
    print("Homepage loaded")
driver.get(driver.current_url+'/c/announcements/5')
WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/head/title')))
print('Trying announcements page')
print(driver.title)

最终想要实现这个目标。

如果(从无头浏览器的本地存储中获取过期时间 >= 现在)
{
#运行生成 cookie(此部分存在问题,需要使其自动化,目前部分是手动的)

#将 cookies.pkl 文件上传到适当的目录
}
否则{
#运行 lopin_12.py 进行登录
}

#访问无头 Chrome 浏览器的本地存储

#在本地存储变量中添加/更新过期日期

如何以及为何?
您可以自动填写电话号码(在哪里询问?)并为该用户关闭 OTP?

1 个赞

@RGJ 是否有任何端点或 API 可供调用以获取有效的登录访问令牌?

如果你想让人们通过你的其他应用程序登录 Discourse,或者通过 Discourse 登录你的其他应用程序,那么你应该实现 DiscourseConnect,我上面已经链接了。你可以查看该页面以获取文档和代码示例。

我还是不太清楚你到底想实现什么。

如果你需要集成另一个网页,并以 Discourse 的身份验证作为事实来源,你可以使用 Discourse 作为 SSO 提供商

如果你需要向 Discourse 的 API 发起服务器到服务器的调用,你可以在 /admin/api/keys 创建 API 密钥。

你能分享一下你想要解决的功能需求吗?

2 个赞

我们有一个名为 login_12.py 的文件,它每 5 分钟测试一次 discourse 登录功能。

我们需要在 login_12.py 中添加 cookies (cookies.pkl) 才能正确登录。

我们是如何获得 cookies (cookies.pkl) 的?
我们有另一个名为 generate_cookies.py 的文件,在该文件中,我们硬编码了用户电子邮件和密码,使用它们,我们为特定用户生成 cookies 并写入 cookies.pkl 文件。

为了生成 cookies,我们使用了浏览器,而我们想避免这种情况,并希望通过代码自动完成此步骤,而无需使用浏览器。

generate_cookies.py 的内容

from selenium import webdriver
import undetected_chromedriver as uc
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pickle


options = uc.ChromeOptions()
#options.add_argument('--headless')
options.add_argument("--disable-extensions")
options.add_argument("--disable-popup-blocking")
options.add_argument("--profile-directory=Default")
options.add_argument("--ignore-certificate-errors")
options.add_argument("--disable-plugins-discovery")
options.add_argument("--incognito")
options.add_argument("user_agent=DN")


if __name__ == "__main__":    #仅 Windows 需要 (undetected_chromedriver 的 bug)
    driver = uc.Chrome(options=options)

    # 登录
    GMAIL = 'discourse.testing@gmail.com'
    PASSWORD = 'discoursetest123'

    driver.get("https://forum.discourse.org/")
    print(driver.title)
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
    print('Homepage loaded')


    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.CLASS_NAME, 'login-button')))
    login = driver.find_elements_by_class_name("login-button")[0]
    print(login)
    login.send_keys(Keys.RETURN)
    print(driver.current_url)
    driver.get(driver.current_url)
    print("email")
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
    print('Email page loaded')
    #print(driver.page_source)

    driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input").send_keys(GMAIL)
    driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div/div[1]/div/div[1]/input").send_keys(Keys.RETURN)
    print("Email entered")

    time.sleep(3)

    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
    print('Password page loaded')
    #print(driver.page_source)

    driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input").send_keys(PASSWORD)
    driver.find_element_by_xpath("/html/body/div[1]/div[1]/div[2]/div/div[2]/div/div/div[2]/div/div[1]/div/form/span/section/div/div/div[1]/div[1]/div/div/div/div/div[1]/div/div[1]/input").send_keys(Keys.RETURN)
    print("Password entered")
    time.sleep(3)

    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/body')))
    print('Login completed')
    print(driver.title)

    #print(driver.find_element_by_xpath("/html/body").get_attribute('innerHTML'))

    if not "Discourse Forum" in driver.title:
        raise Exception('login Error')
    else:
        print("Homepage loaded")
    driver.get(driver.current_url+'/c/announcements/5')
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, '/html/head/title')))
    print('Trying announcements page')
    print(driver.title)
    if not "Latest Announcements topics - Discourse Forum" in driver.title:
        raise Exception('login Error function')
    print("Success!")

    pickle.dump( driver.get_cookies() , open("cookies2.pkl","wb"))

这是一个更偏向 Python 的问题。

你可以使用 Python 中的 Requests 库来发出请求。它支持多种方式处理 cookies,这里 有一些示例。我建议你使用 Session 对象。

如果你想解析 HTML 输出,可以使用 BeautifulSoup

1 个赞

所以您想做的是持续测试登录是否有效?您不是想做任何事情。您只是想确保如果有人尝试登录您的网站,它(很可能)会成功?