今天做的练习是抓取人民网上面的新闻,和第一篇笔记不同的是这次点击链接是在新窗口打开,涉及到切换窗口抓取的问题。xpath方法是定位到具体层级的,不能跳跃地忽略父从爷定位到孙。由于这次的案例是a标签被包裹在不同的父div中,所以可以用*表示任意父div,再定位到后面的p/strong/a里:
links=driver.find_elements_by_xpath("/html/body/div[14]/div[1]/div/*/p/strong/a")
这里抓取出来的a标签内的元素组成了列表links,列表不能点击,但是列表里的单个元素可以,所以用遍历循环的方法将列表元素逐个赋给link
link=links[i]
这里的link是单一元素,所以可以click了。这里终于解决了第一篇笔记里面遇到的问题,当时发现抓取到所有的链接组成列表links,死活不能用click(因为列表理所当然是不能click的啊),后来只能用get_attribute(href)的方法获取链接,但这里获取到的链接是字符串,还得用get(url)在原窗口打开。现在发现了只需要定位到包裹href链接的a标签,就能通过遍历循环把列表links逐一提取点击:
link.click()
打开了新窗口后,获取全部窗口的句柄(即系统给窗口的编码,如:你正在操作142号窗口)
handles=driver.window_handles
虽然点击链接新开了窗口,但是即使有打开新的窗口,浏览器还是会focus在原来的窗口,所以我们先记录一下原来的主窗口:
index_handle=driver.current_window_handle #这里的current_window_handle还是主窗口
用循环来遍历所有窗口,因为浏览器focus在主窗口,这里用if来判断,如果窗口不是主窗口,就让浏览器切换到新窗口
for handle in handles:
if handle != index_handle: #如果不是主窗口
driver.switch_to.window(handle) #切换到新窗口
else:
continue #继续循环
抓取后回到主窗口index_handle:
driver.switch_to_window(index_handle)
完整代码如下:
from selenium import webdriver
import time
driver=webdriver.Chrome()
driver.get("http://energy.people.com.cn/")
time.sleep(1)
links=driver.find_elements_by_xpath("/html/body/div[14]/div[1]/div/*/p/strong/a")
length=len(links)
for i in range(0,length):
links=driver.find_elements_by_xpath("/html/body/div[14]/div[1]/div/*/p/strong/a")#这里抓取出来的组成了列表links,列表不能点击,但是列表里的单个元素可以
link=links[i]
link.click() #为什么这里就可以click呢?因为通过前面links[i]将列表逐个赋给link后,这里的link是单一元素,所以可以click
time.sleep(1)
handles=driver.window_handles #获取当前全部窗口
index_handle=driver.current_window_handle #虽然点击了链接新开了窗口,但是即使有打开新的窗口,浏览器还是会focus在原来的窗口,所以这里的current_window_handle还是主页
for handle in handles: #判断窗口是否为新窗口,还是原来的主页窗口
if handle != index_handle: #如果不是主页窗口
driver.switch_to.window(handle) #切换到新窗口
else:
continue #是主页窗口则继续下一个循环
title=driver.find_element_by_xpath("/html/body/div[5]/h1").text
print(title)
content=driver.find_element_by_xpath("//*[@id='rwb_zw']").text #这里本身写了//*[@id='p-detail']/p,但是这个div下面有很多个p标签进行分段,这样写只能抓取到第一段,第二段是p[1],所以干脆不写p,直接抓取div下面的纯文本
print(content)
print("\n")
driver.close()
time.sleep(1)
driver.switch_to_window(index_handle)
driver.quit()
print("————人民网抓取完毕,共",length,"条新闻————")