爬虫11天——selenium实战
一、目的:爬取阳光视频网的多个视频,下载到本地
二、网站分析:
1.网站结构分为:视频列表页和视频详情页
2.右键检查视频列表网页:

发现:每条视频都是一个class叫"title-box"的div,然后视频详情页的链接在这个div下面的a标签
3.进入视频详情页,检查网页:

发现:视频地址在id为"vs"的div标签下面的video标签里面
三、爬取过程:
1.最初爬取代码:
#需求:爬取阳光宽频网的视频,下载到本地
from selenium import webdriver
import time
import requests#阳光宽频网爬取类
class ygkp:video_url_list = []url_list = []#1.驱动——返回驱动driverdef get_driver(self):# 1.selenium配置# 1.1 设置请求头options = webdriver.ChromeOptions()options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")driver = webdriver.Chrome(options=options)return driver# #1.5 关闭底部banner页# def close_bottom_banner(self,driver):# #定位关闭按钮# close_bt = driver.find_element_by_class_name("close-banner-icon")# #点击关闭按钮# close_bt.click()#2.视频列表页——返回视频网页链接元素列表def get_video_list_page(self,driver):#2.进入网站driver.get("https://365yg.com/")time.sleep(5)#3.获取视频详情页链接video_div_url_list = driver.find_elements_by_class_name("title-box")#print("video_div_url_list" + str(video_div_url_list))for div in video_div_url_list:#print("div" + str(div))a = div.find_element_by_tag_name("a")self.video_url_list.append(a)#url = a.get_attribute("href")#self.url_list.append(url)#3.视频详情页——返回视频的URLdef get_video_url(self,driver,num):time.sleep(5)if num == 1:driver.switch_to.window(driver.window_handles[num+1])else:driver.switch_to.window(driver.window_handles[-1])driver.save_screenshot("01.png")div = driver.find_element_by_id("vs")#print("video_div" + str(div))time.sleep(5)video_src = div.find_element_by_tag_name("video").get_attribute("src")#print("video_src" + str(video_src))return video_src#4.下载视频def download_video(self,num,video_src):response = requests.get(video_src).contentwith open("shipin" + str(num+1) + ".mp4", "wb") as f:f.write(response)
#5.运行def run(self):#1.获取驱动driver = self.get_driver()#2.获取视频详情页列表self.get_video_list_page(driver=driver)print(str(len(self.video_url_list)))#3.关闭底部banner页#self.close_bottom_banner(driver=driver)#print("video_url_list"+str(self.video_url_list))#4.点击每个视频链接for i, video_web_url in enumerate(self.video_url_list):driver.switch_to.window(driver.window_handles[0])print("video_web_url" + str(i+1) +":" + str(video_web_url))#print("url" + str(i+1) + ":" + str(self.url_list[i]))time.sleep(10)video_web_url.click()#driver.execute_script("arguments[0].click();", video_web_url)#5.获取每个视频的URL地址video_src = self.get_video_url(driver=driver,num=i)#6.下载urlself.download_video(num=i,video_src=video_src)ygkp().run()
结果报错:

2.
在网上查询到,有两种解决办法:
#方法1:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]')
driver.execute_script("arguments[0].click();", element)#方法2:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]')
webdriver.ActionChains(driver).move_to_element(element ).click(element ).perform()
我都试了一遍,结果,不会再报这个错误,但是后面会反复进入同一个详情页,反复下载同一个视频

再次查询ElementClickInterceptedException: Message: element click intercepted报错原因:发现原来是由于已经定位到的目标元素被其他元素遮挡,所以无法点击该元素。
查看网页:

发现:视频列表页,底部有banner页,挡住了第五条视频。所以,无法点击。就像用户操作鼠标一样,当banner页覆盖了第五条视频时,用户无法用鼠标点击到该条视频。这应该就是所说的——页面元素存在遮挡
再次查看报错信息:

也是在点击第五条视频时,出现错误。
解决方法:第一次进入视频列表网页时,就先立即关闭banner页,然后再逐个点击视频。
检查网页:

关闭banner的X按钮,class叫“close-banner-icon”
修改后代码:
#需求:爬取阳光宽频网的视频,下载到本地
from selenium import webdriver
import time
import requests#阳光宽频网类
class ygkp:video_url_list = []url_list = []#1.驱动——返回驱动driverdef get_driver(self):# 1.selenium配置# 1.1 设置请求头options = webdriver.ChromeOptions()options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")driver = webdriver.Chrome(options=options)return driver#1.5 关闭底部banner页def close_bottom_banner(self,driver):#定位关闭按钮close_bt = driver.find_element_by_class_name("close-banner-icon")#点击关闭按钮
close_bt.click()#2.视频列表页——返回视频网页链接元素列表def get_video_list_page(self,driver):#2.进入网站driver.get("https://365yg.com/")time.sleep(5)#3.获取视频详情页链接video_div_url_list = driver.find_elements_by_class_name("title-box")#print("video_div_url_list" + str(video_div_url_list))for div in video_div_url_list:#print("div" + str(div))a = div.find_element_by_tag_name("a")self.video_url_list.append(a)#url = a.get_attribute("href")#self.url_list.append(url)#3.视频详情页——返回视频的URLdef get_video_url(self,driver,num):time.sleep(5)if num == 1:driver.switch_to.window(driver.window_handles[num+1])else:driver.switch_to.window(driver.window_handles[-1])driver.save_screenshot("01.png")div = driver.find_element_by_id("vs")#print("video_div" + str(div))time.sleep(5)video_src = div.find_element_by_tag_name("video").get_attribute("src")#print("video_src" + str(video_src))return video_src#4.下载视频def download_video(self,num,video_src):response = requests.get(video_src).contentwith open("shipin" + str(num+1) + ".mp4", "wb") as f:f.write(response)#5.运行def run(self):#1.获取驱动driver = self.get_driver()#2.获取视频详情页列表self.get_video_list_page(driver=driver)print(str(len(self.video_url_list)))#3.关闭底部banner页self.close_bottom_banner(driver=driver)#print("video_url_list"+str(self.video_url_list))#4.点击每个视频链接for i, video_web_url in enumerate(self.video_url_list):driver.switch_to.window(driver.window_handles[0])print("video_web_url" + str(i+1) +":" + str(video_web_url))#print("url" + str(i+1) + ":" + str(self.url_list[i]))time.sleep(10)video_web_url.click()#driver.execute_script("arguments[0].click();", video_web_url)#5.获取每个视频的URL地址video_src = self.get_video_url(driver=driver,num=i)#6.下载urlself.download_video(num=i,video_src=video_src)ygkp().run()
这样就能正常爬取了
四、补充:
查看视频列表长度,发现:每次只能获取7条视频。
这是因为,网站视频列表是动态加载的。每次滑动到底部会再加载新的7条视频。
如果我们要想爬取所有视频,该怎么办呢?
解决方法:先爬取最初的7条视频,然后每次爬取之前,都将网页滚动到浏览器底部,待加载出新的视频后,再次爬取。为了防止视频element有重复,可以使用set集合存放视频element。
#需求:爬取阳光宽频网的视频,下载到本地
from selenium import webdriver
import time
import requests#阳光宽频网类
class ygkp:video_url_list = set()url_list = set()#1.驱动——返回驱动driverdef get_driver(self):# 1.selenium配置# 1.1 设置请求头options = webdriver.ChromeOptions()options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36")driver = webdriver.Chrome(options=options)return driver#1.5 关闭底部banner页def close_bottom_banner(self,driver):#定位关闭按钮close_bt = driver.find_element_by_class_name("close-banner-icon")#点击关闭按钮
close_bt.click()#2.视频列表页——返回视频网页链接元素列表def get_video_list_page(self,driver):# #2.进入网站# driver.get("https://365yg.com/")# time.sleep(5)#3.获取视频详情页链接video_div_url_list = driver.find_elements_by_class_name("title-box")#print("video_div_url_list" + str(video_div_url_list))for div in video_div_url_list:#print("div" + str(div))a = div.find_element_by_tag_name("a")self.video_url_list.add(a)url = a.get_attribute("href")self.url_list.add(url)#3.视频详情页——返回视频的URLdef get_video_url(self,driver,num):time.sleep(5)if num == 1:driver.switch_to.window(driver.window_handles[num+1])else:driver.switch_to.window(driver.window_handles[-1])driver.save_screenshot("01.png")div = driver.find_element_by_id("vs")#print("video_div" + str(div))time.sleep(5)video_src = div.find_element_by_tag_name("video").get_attribute("src")#print("video_src" + str(video_src))return video_src#4.下载视频def download_video(self,num,video_src):response = requests.get(video_src).contentwith open("shipin" + str(num+1) + ".mp4", "wb") as f:f.write(response)
#5.运行def run(self):#1.获取驱动driver = self.get_driver()# 2.进入网站driver.get("https://365yg.com/")time.sleep(5)# 3.关闭底部banner页self.close_bottom_banner(driver=driver)#2.获取视频详情页列表for i in range(5):self.get_video_list_page(driver=driver)print(str(len(self.video_url_list)))driver.execute_script("window.scrollTo(0,document.body.scrollHeight)")time.sleep(5)#print("video_url_list"+str(self.video_url_list))#4.点击每个视频链接# for i, video_web_url in enumerate(self.video_url_list):# driver.switch_to.window(driver.window_handles[0])# print("video_web_url" + str(i+1) +":" + str(video_web_url))# print("url" + str(i+1) + ":" + str(self.url_list[i]))# time.sleep(10)# video_web_url.click()# #driver.execute_script("arguments[0].click();", video_web_url)# #5.获取每个视频的URL地址# video_src = self.get_video_url(driver=driver,num=i)# #6.下载url# self.download_video(num=i,video_src=video_src)
ygkp().run()
运行结果:

可以看到:视频列表的长度增加了。
如果想爬取所有视频,可以将for循环改成while循环。
五:总结:
我学到了:
1.元素element定位有多种方式:
https://i.cnblogs.com/EditPosts.aspx?postid=11127907
2. 获取element的属性值:get_attribute("属性名")
3.下载视频、图片:
https://i.cnblogs.com/EditPosts.aspx?postid=11127907
4.报错:element click intercepted的原因
是由于网页上,存在页面元素相互遮挡,无法点击到目标元素
解决方法:
#方法1:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]')
driver.execute_script("arguments[0].click();", element)#方法2:
element = driver.find_element_by_css('div[class*="loadingWhiteBox"]')
webdriver.ActionChains(driver).move_to_element(element ).click(element ).perform()
方法3:
关闭掉,遮挡元素;总之,想法设法将被遮挡的点击目标元素,露出来。
5.selenium滑动浏览器:
#移动到元素element对象的“顶端”与当前窗口的“顶部”对齐
driver.execute_script("arguments[0].scrollIntoView();", element);
driver.execute_script("arguments[0].scrollIntoView(true);", element);
#移动到元素element对象的“底端”与当前窗口的“底部”对齐
driver.execute_script("arguments[0].scrollIntoView(false);", element); #移动到页面最底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)"); #移动到指定的坐标(相对当前的坐标移动)
driver.execute_script("window.scrollBy(0, 700)");
#结合上面的scrollBy语句,相当于移动到700+800=1600像素位置
driver.execute_script("window.scrollBy(0, 800)"); #移动到窗口绝对位置坐标,如下移动到纵坐标1600像素位置
driver.execute_script("window.scrollTo(0, 1600)");
#结合上面的scrollTo语句,仍然移动到纵坐标1200像素位置
driver.execute_script("window.scrollTo(0, 1200)"); 6.python中set集合的用法:
转载于:https://www.cnblogs.com/tommyngx/p/11156571.html
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
