做过selenium爬虫的人,一定有一个烦恼,那就是selenium会启动很多子进程,爬虫终止的时候,由于各种原因,总会有些僵尸进程(chrome,chromedriver)残留在内存,不清除这些僵尸就无法进行大规模的爬行。
在网上搜索了半天,终于发现一个有用的文章
https://gist.github.com/valantonini/452cf90254e50617f6273bab8c34b1dc
这个程序就是调用windows的api,把主进程和子进程捆绑成一个job,杀死主进程就杀死子进程,这个叫同生共死,终于可以和僵尸拜拜了。
我把这个稍微封装下,加了获取子进程树和去重复的功能
public static Job m_job = new Job();
private static HashSet<int> childrenPid = new HashSet<int>();
public static void AddChildrenProcess(int pid)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
ManagementObjectCollection moc = searcher.Get();
foreach (ManagementObject mo in moc)
{
AddChildrenProcess(Convert.ToInt32(mo["ProcessID"]));
}
if( !childrenPid.Contains(pid))
{
m_job.AddProcess(pid);
childrenPid.Add(pid);
}
}
调用方法如下,注意,一定要在new ChromeDeriver后调用,在new之前调用的哈,由于还没有启动driver,ProcessId为空会导致调用失败。
m_chromeDriverService = ChromeDriverService.CreateDefaultService(System.Environment.CurrentDirectory);
...
m_driver = new ChromeDriver(m_chromeDriverService, options, TimeSpan.FromSeconds(180));
AddChildrenProcess(m_chromeDriverService.ProcessId);