【Selenium & Other】使用quit()无法关闭窗口 & 一键杀死进程

前言

有位读者留言,遇到了一件两难全的事儿。在关闭Python使用os模块执行cmd命令调用的chromedriver驱动打开的chrome浏览器时,有以下问题~

  • 使用driver.quit()退出浏览器,chromedriver.exe进程退出,关闭没有窗口
  • 使用driver.close()退出浏览器,chromedriver.exe进程没有退出,窗口关闭

但是咱们这里全都要,下面就来解决它,顺便说一下关于杀死进程的事儿~

文章链接在这:

标题链接
【Selenium】Selenium绕过检测 & 隐藏特征【Selenium】Selenium绕过检测 & 隐藏特征

问题在这:

解决方法如下:

  • 先关闭窗口,再杀掉 chromedriver.exe 进程。
driver.close()
driver.quit()

全文完~🎈🎈
下面且再吧啦一下吧🏹🏹


问题复现

这份代码贯穿全文,将用于多次示例。

执行以下代码,详情看动图

  • 执行以下代码,会启动一个名为 chromedriver.exe的进程,通过任务管理器 可看到
# -*- coding: utf-8 -*-
# Name:         hide_features.py
# Author:       小菜
# Date:         2022/8/29 15:43
# Description:

import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

if __name__ == '__main__':
    os.system(r'start chrome --remote-debugging-port=9527 --user-data-dir="F:\selenium"')
    options = Options()
    options.add_experimental_option("debuggerAddress", "127.0.0.1:9527")
    driver = webdriver.Chrome(options=options)
    driver.get('https://bot.sannysoft.com/')
    # driver.quit()
    driver.close()

这个是 drivrt.quit()

  • 可以看到,chromedriver.exe 进程退出了,但窗口没有关闭

请添加图片描述

这个是 drivrt.close()

  • 可以看到,chromedriver.exe 进程没有退出,但窗口关闭了。

在这里插入图片描述

问题成功复现,下面解决它。


解决方法

全程注意打开 任务管理器,实时查看 chromedriver.exe进程的情况~

这里准备两种解决方法,

  1. 通过Python
  2. 通过Windows系统的taskkill(终止进程命令

两种方法

  • 直接杀死chrome进程
  • 杀死置顶端口的进程

Python实现

跟一下 driver.quit(),看到以下源码,不管执行成功与否,最终都是执行了 self.service.stop()

def quit(self) -> None:
    """
    Closes the browser and shuts down the ChromiumDriver executable
    that is started when starting the ChromiumDriver
    """
    try:
        super().quit()
    except Exception:
        # We don't care about the message because something probably has gone wrong
        pass
    finally:
        self.service.stop()

这里我们改一下代码,将 driver.quit() 修改 成以下

  • 先挂关闭浏览器,再停止service,可以达到杀死chromedriver.exe进程和关闭窗口的两全其美。
driver.close()
driver.service.stop()

然后执行代码,看以下动图

完美解决问题~


Windows系统命令

这里会用到两个Windows的命令,分别是 netstattaskkill

可以通过以下链接获得更详细的介绍🎈

命令链接
netstathttps://docs.microsoft.com/zh-cn/windows-server/administration/windows-commands/netstat
taskkillhttps://docs.microsoft.com/zh-cn/windows-server/administration/windows-commands/taskkill

参数:

在这里插入图片描述

netstat

命令用于显示活动的TCP链接、正在使用的端口等~

官方介绍截图如下:

执行 driver.close() 的代码之后,chromedriver.exe 进程的状态还是 正在运行的,
现在打开电脑的cmd 窗口,输入以下命令,然后回车

netstat -ano | findstr 9527

代码释义( 查找所有活动的TCP连接中包含9527的连接

  • netstat -ano:显示活动的TCP连接
  • findstr:Windows系统命令,用于查找指定的包含的字符串
  • 9527:因为上面的代码中指定打开的端口是 9527

运行如下图所示:

看到有两个TCP连接,这里后面跟的是它们的PID(Process Identification
干掉任意下面那个状态为CLOSE_WAIT进程 就可以结束 chromedriver.exe 进程啦🐱‍🏍

接下来去干掉它!!!

taskkill

Windows系统自带命令,用于结束一个或多个进程~

官方介绍截图如下:

上面我们知道了 活动的 TCP连接,这里来干了它。

taskkill /f /t /pid 2024

代码释义(强制结束 pid2024 的进程,你需要改为你的进程 pid

  • /f:指定强制结束进程
  • /t:结束指定进程以及由该进程启动的任何子进程
  • /pid <processID>:指定要终止的进程的进程 ID。

运行如下图所示:

  • 成功结束chromederiver.exe进程

改写成 Python代码如下:

  • 同样可以达到杀死chromedriver.exe 进程的目的~
import os
result = os.popen('netstat -ano | findstr 9527 | findstr CLOSE_WAIT')
port = result.strip().split('      ')[-1]
os.popen(f'taskkill /f -t /pid {port}')

但是!!!
这个方法不是特别妙,有没有更妙的方法呢?答案是没有!不存在完美的方法🎃🎃


tasklist

显示本地计算机或远程计算机上当前正在运行的进程列表。

官方介绍截图如下:

使用 tasklist 查看包含 chromedriver.exe的进程,然后再干掉它。

  • 会存在误杀,你开启了两个窗口,端口分别是1234 和 9527,但不清楚哪个窗口对应哪个端口,所以可能会误杀~
tasklist | findstr chromedriver.exe

如下图:

  • 可以获取到它的 PID,后面去干掉对应的 PID 就完事了

在这里插入图片描述

结合写法

如果进程存在就kill 了它

tasklist | find /i "chromedriver.exe" > nul && taskkill /f /im "chromedriver.exe" > nul

关闭N个程序

思路发散一下,可以关闭多个电脑程序,不局限于Selenium浏览器的使用。

杀死指定进程

  • im: 指定要终止的进程的映像名称
taskkill /f /t /im chromedriver.exe

如下所示:

  • 杀死所有进程名为 chromedriver.exe 的进程

一行命令杀死多个进程

  • 这里干掉了4个进程树,甚至还关闭 cmd窗口~
  • 思路再发散一下,将平时经常会打开的程序都添加到这行代码里面去,然后编写成.bat批处理文件,一键执行关闭指定N个程序,实在不济,下面也还有个一键关闭所有程序的~
taskkill /f /t /im msedge.exe /im wps.exe /im Typora.exe /im cmd.exe

运行如下所示:

干掉所有程序

taskkill /F /FI "USERNAME eq 【您的用户名】" /FI "IMAGENAME ne explorer.exe" /FI "IMAGENAME ne dwm.exe,

代码释义:

  • 意思是在此用户账户下筛选 explorer.exe(文件资源管理器)和 dwm.exe(桌面窗口管理器),将这两项强制终止进程,即可达到关闭所有程序的目的。

后话

see you.🐱‍🏍🐱‍🏍