首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用selenium、python和whatsapp-web等待元素显示而不显示。

使用selenium、python和whatsapp-web等待元素显示而不显示。
EN

Stack Overflow用户
提问于 2019-01-18 00:23:39
回答 2查看 1.4K关注 0票数 2

我试图使用" whatsapp -web“、"selenium”和"python 3“来了解whatsapp用户何时上线或离线。

为了解释更多,我希望脚本工作如下:

脚本将侦听要显示的span (带有title=online),当span显示时(这意味着用户在线),我希望此时打印时间,然后脚本将继续侦听以使span消失,当脚本消失时,脚本打印消失的时间,等等。

这是我的密码:

代码语言:javascript
运行
复制
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import datetime

driver = webdriver.Chrome('C:/webdrivers/chromedriver.exe')
driver.get('https://web.whatsapp.com/')

# do nothing until QR code scanned and whatsapp-web is accessed
input('Enter anything after scanning QR code')

# Input the name of the user to track
name = input('Enter the name of the user : ')

# find the whatsapp user to be tracked then a click to enter the conversation
user = driver.find_element_by_xpath("//span[@title = '{}']".format(name))
user.click()

while True:
   # in the conversation page, a span with title online is diplayed when user is online.
   #the web driver will wait 8hrs=28800s, if user not online all this time script will be killed by webdriverWait
   element = WebDriverWait(driver, 28800).until(
      EC.visibility_of_element_located(
         (By.XPATH, "//span[@title = 'online']")))

   #Moment the user came online
   now = datetime.datetime.now()
   print("online at : ")
   print(now.strftime("%H:%M:%S"))

   element = WebDriverWait(driver, 28800).until(
      EC.invisibility_of_element_located(
         (By.XPATH, "//span[@title = 'online']")))

   #Moment the user went offline
   now = datetime.datetime.now()
   print("offline at : ")
   print(now.strftime("%H:%M:%S"))
   print("************")

我的脚本可以工作,但是,我希望它运行几个小时,比如8小时甚至更长时间,但我读到使用坏实践时使用WebDriverWait的时间很长(在我的例子中是28800秒)。

,那么还有其他更好的方法来实现这一点吗?

如何将输出写入txt或word文件?

有让我的代码更好的建议吗?

如何防止CPU猛击?或任何可能发生的问题

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-18 06:58:43

WebDriverWait不过是(相当)花哨的同时/捕捉/睡眠循环;在您的特殊情况下,您可能希望自己复制它,原因很简单--它每500毫秒进行一次投票,对于这项任务来说,这可能太详细了。它也能保护你不受更细粒度的控制。

下面是如何自己执行逻辑的方法--有一个布尔变量是用户在线与否;根据它的值,check是可见元素(.is_displayed()),睡眠X时间和重复。异常NoSuchElementExceptionStaleElementReferenceException将计算为脱机用户/布尔值false。

最后,您的代码将非常接近WebDriverWait中的逻辑--尽管如此,如果需要,您的代码也会更加灵活。

或者,只需在当前代码中的WebDriverWait内部传递一个更大的轮询-它是调用的poll_frequency参数:)

代码语言:javascript
运行
复制
WebDriverWait(driver, 28800, 5)  # the value is in seconds

我不知道你在哪里读到了什么--用很长的时间使用WebDriverWait是不好的做法;正如您在它的代码中所看到的,它只是给该方法运行的时间而已。

我猜想这条建议是以“用大量秒来使用WebDriverWait是一种不好的做法,因为如果条件在X秒内没有得到满足,它将永远不会被满足,而您的代码只会旋转和旋转。”这实际上是您想要的行为:)

我也不会担心对cpu征税--这些检查非常轻巧,没有什么害处。对于这个大的运行时,我担心的是浏览器本身的内存泄漏;)

至于优化代码,我要做的是减少语句的重复,这样做的缺点是降低了代码的可读性。我对循环的看法:

代码语言:javascript
运行
复制
user_online = False

while True:
    # we'll be checking for the reverse of the last status of the user
    check_method = EC.visibility_of_element_located if not user_online else EC.invisibility_of_element_located

    # in the conversation page, a span with title online is diplayed when user is online.
    # the web driver will wait 8hrs=28800s for the user status to change all
    # the script will be killed by webdriverWait if that doesn't happen
    element = WebDriverWait(driver, 28800, 5).until(
            check_method((By.XPATH, "//span[@title = 'online']")))

    # The moment the user changed status
    now = datetime.datetime.now().strftime("%H:%M:%S")
    print("{} at : {}".format('online' if not user_online else 'offline', now))   # if you're using python v3.6 or more, the fstrings are much more convenient for this
    print("************")

    user_online = not user_online   # switch, to wait for the other status in the next cycle

最后,就代码而言,不能让脚本“没完没了地”运行。为什么?因为如果用户在8小时内不改变状态,WebDriverWait就会停止。若要挽救该问题,请将循环主体封装在try/except中:

代码语言:javascript
运行
复制
from selenium.common.exceptions import TimeoutException  # put this in the beginning of the file

while True:
    try:
        # the code from above
    except TimeoutException:
        # the status did not change, repeat the cycle
        pass

写入文件

您可能需要阅读 a how 要做到这一点 -这是一个非常简单的操作。

下面是一个示例-打开一个用于追加的文件(因此保留了以前的日志),包装while循环:

代码语言:javascript
运行
复制
with open("usermonitor.log", "a") as myfile:
    while True:
        # the other code is not repaeted for brevity
        # ...
        output = "{} at : {}".format('online' if not user_online else 'offline', now)
        print(output)
        myfile.write(output + "\n")  # this will write (append as the last line) the same text in the file
        # write() does not append newlines by itself - you have to do it yourself
票数 1
EN

Stack Overflow用户

发布于 2021-07-22 21:19:20

我要建议的是,在您的程序中,每次执行此程序时都需要扫描whatsapp,只需替换这一行。

driver = webdriver.Chrome('C:/webdrivers/chromedriver.exe')

有了这个

代码语言:javascript
运行
复制
driver = webdriver.Chrome('C:/webdrivers/chromedriver.exe', options="user-data-dir=C:\\Users\\<username>\\AppData\\Local\\Google\\Chrome\\User Data\\whtsap")

这样你就需要扫描QR,但只需要扫描一次。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54246168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档