爬虫-----selenium模块自动爬取网页资源
selenium介绍与使用
1 selenium介绍
什么是selenium?selenium是Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作。
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题 selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉 等,来拿到网页渲染之后的结果,可支持多种浏览器.
2 下载安装
下载驱动 http://npm.taobao.org/mirrors/chromedriver/2.35/
下载chromdriver.exe放到python安装路径的scripts目录中即可,注意最新版本是2.38,并非2.9
pip install selenium
3 使用
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys # 键盘上操作键的模块 # 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的
driver = webdriver.Chrome()
# 用get打开百度页面
driver.get("http://www.baidu.com")
# 查找页面的“设置”选项,并进行点击
driver.find_elements_by_link_text('设置')[0].click()
sleep(2)
# # 打开设置后找到“搜索设置”选项,设置为每页显示50条
driver.find_elements_by_link_text('搜索设置')[0].click()
sleep(2) # 选中每页显示50条
m = driver.find_element_by_id('nr')
sleep(2)
m.find_element_by_xpath('//*[@id="nr"]/option[3]').click()
m.find_element_by_xpath('.//option[3]').click()
sleep(2) # 点击保存设置
driver.find_elements_by_class_name("prefpanelgo")[0].click()
sleep(2) # 处理弹出的警告页面 确定accept() 和 取消dismiss()
driver.switch_to.alert().accept()
sleep(2)
# 找到百度的输入框,并输入 美女
driver.find_element_by_id('kw').send_keys('美女')
sleep(2)
# 点击搜索按钮
driver.find_element_by_id('su').click()
# (或者在输入框输入之后直接driver.send_keys(Keys.ENTER)表示按下回车键)
sleep(2)
# 在打开的页面中找到“Selenium - 开源中国社区”,并打开这个页面
driver.find_elements_by_link_text('美女_百度图片')[0].click()
sleep(3) # 关闭浏览器
driver.quit()
4 元素定位
find_element_by_id()
find_element_by_name()
find_element_by_class_name()
find_element_by_tag_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_xpath()
find_element_by_css_selector()
# 这些都有对应的 find_elements_by...相对应 # 注意: find_elements_by...拿到的是一个列表
find_element_by...拿到的是一个tag对象
5 节点交互
Selenium可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作。比较常见的用法有:输入文字时用send_keys()方法,清空文字时用clear()方法,点击按钮时用click()方法。
from selenium import webdriver
import time browser = webdriver.Chrome()
browser.get('https://www.taobao.com')
input = browser.find_element_by_id('q')
input.send_keys('MAC') # 输入搜索词条
time.sleep(1)
input.clear() # 清除词条
input.send_keys('IPhone')
button = browser.find_element_by_class_name('btn-search')
button.click() #点击搜索按钮
6 动作链
在上面的实例中,一些交互动作都是针对某个节点执行的。比如,对于输入框,我们就调用它的输入文字和清空文字方法;对于按钮,就调用它的点击方法。其实,还有另外一些操作,它们没有特定的执行对象,比如鼠标拖曳、键盘按键等,这些动作用另一种方式来执行,那就是动作链。比如,现在实现一个节点的拖曳操作,将某个节点从一处拖曳到另外一处,可以这样实现:
from selenium import webdriver
from selenium.webdriver import ActionChains
import time
browser = webdriver.Chrome()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')
actions = ActionChains(browser)
# actions.drag_and_drop(source, target)
actions.click_and_hold(source).perform() # 点击并且按住
time.sleep(1)
actions.move_to_element(target).perform() # 移动到target位置
time.sleep(1)
actions.move_by_offset(xoffset=50,yoffset=0).perform() # 从当前位置再沿x轴平移50个单位
actions.release()
7 执行js动作
对于某些操作,Selenium API并没有提供。比如,下拉进度条,它可以直接模拟运行JavaScript,此时使用execute_script()方法即可实现,代码如下:
from selenium import webdriver browser = webdriver.Chrome()
browser.get('https://www.jd.com/')
browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("123")')
如何判断滚动条已经下拉到最后的位置了? 代码如下:
from selenium import webdriver
from time import sleep url = "https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action="
path = "./phantomjs-2.1.1-windows/bin/phantomjs.exe" height_list = [] # 用来放每次的拖动滚动条后页面的最大高度
browser = webdriver.PhantomJS(executable_path=path)
browser.get(url)
height_list.append(browser.execute_script("return document.body.scrollHeight")) # 放第一次拖动滚动条后页面的最大高度 while 1:
browser.execute_script("scroll(0,1000000)") # 拖动滚动条, 取值范围足够大
sleep(1)
check_height = browser.execute_script("return document.body.scrollHeight")
# 获取每次拖动的文档高度
if check_height == height_list[-1]: # 判断拖动滚动条后的最大高度与上一次的最大高度的大小,相等表明到了最底部
break
height_list.append(check_height) print(height_list) # [1000, 2480, 4391, 6301, 8211, 10121, 12031, 13941, 15851, 17761, 19098]
8 延时等待
在Selenium中,get()方法会在网页框架加载结束后结束执行,此时如果获取page_source,可能并不是浏览器完全加载完成的页面,如果某些页面有额外的Ajax请求,我们在网页源代码中也不一定能成功获取到。所以,这里需要延时等待一定时间,确保节点已经加载出来。这里等待的方式有两种:一种是隐式等待,一种是显式等待。
隐式等待:
当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。换句话说,当查找节点而节点并没有立即出现的时候,隐式等待将等待一段时间再查找DOM(在这段时间之内不会查找, n秒之后再进行查找),默认的时间是0。示例如下:
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() #隐式等待:在查找所有元素时,如果尚未被加载,则等10秒, 10秒之后再一次查找
browser.implicitly_wait(10) browser.get('https://www.baidu.com')
input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER) contents=browser.find_element_by_id('content_left') #没有等待环节而直接查找,找不到则会报错
print(contents) browser.close()
显示等待:
隐式等待的效果其实并没有那么好,因为我们只规定了一个固定时间,而页面的加载时间会受到网络条件的影响。这里还有一种更合适的显式等待方法,它指定要查找的节点,然后指定一个最长等待时间。如果在规定时间内加载出来了这个节点,就返回查找的节点;如果到了规定时间依然没有加载出该节点,则抛出超时异常。
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.common.keys import Keys #键盘按键操作
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome()
browser.get('https://www.baidu.com') input_tag=browser.find_element_by_id('kw')
input_tag.send_keys('美女')
input_tag.send_keys(Keys.ENTER) #显式等待:显式地等待某个元素被加载
wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'content_left'))) contents=browser.find_element(By.CSS_SELECTOR,'#content_left')
print(contents) browser.close()
9 获取tag节点的信息
通过page_source属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。
不过,既然Selenium已经提供了选择节点的方法,返回的是WebElement类型,那么它也有相关的方法和属性来直接提取节点信息,如属性、文本等。这样的话,我们就可以不用通过解析源代码来提取信息了,非常方便。
from selenium import webdriver
from selenium.webdriver.common.by import By #按照什么方式查找,By.ID,By.CSS_SELECTOR
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait #等待页面加载某些元素 browser=webdriver.Chrome() browser.get('https://www.amazon.cn/') wait=WebDriverWait(browser,10)
wait.until(EC.presence_of_element_located((By.ID,'cc-lm-tcgShowImgContainer'))) tag=browser.find_element(By.CSS_SELECTOR,'#cc-lm-tcgShowImgContainer img') #获取标签属性,
print(tag.get_attribute('src'))
#获取标签ID,位置,名称,大小(了解)
print(tag.id)
print(tag.location) # {'x': 0, 'y': 133}
print(tag.tag_name)
print(tag.size) # {'height': 1453, 'width': 661} browser.close()
phantomJs介绍与使用
1 PhantomJS介绍
PhantomJS是一款无界面的浏览器,其自动化操作流程和上述操作谷歌浏览器是一致的。由于是无界面的,为了能够展示自动化操作流程,PhantomJS为用户提供了一个截屏的功能,使用save_screenshot("xxx.png")函数实现。
重点:selenium+phantomjs 就是爬虫终极解决方案:有些网站上的内容信息是通过动态加载js形成的,所以使用普通爬虫程序无法回去动态加载的js内容。例如豆瓣电影中的电影信息是通过下拉操作动态加载更多的电影信息。
from selenium import webdriver
import time """
phantomjs, 完完全全模拟浏览器访问url, 期间没有可视化界面
""" time.sleep(1)
bro = webdriver.PhantomJS(executable_path="./phantomjs-2.1.1-windows/bin/phantomjs.exe")
bro.get("https://www.baidu.com/")
time.sleep(2)
text_input = bro.find_element_by_id("kw")
value_btn = bro.find_element_by_id("su")
text_input.send_keys("粪叉子")
value_btn.click()
time.sleep(2)
js = "window.scrollTo(0,document.body.scrollHeight)"
bro.execute_script(js) time.sleep(2)
page_text = bro.page_source
print(page_text)
bro.quit() # 同 bro.close()
2 Google无头浏览器
由于PhantomJs最近已经停止了更新和维护,所以推荐大家可以使用谷歌的无头浏览器,是一款无界面的谷歌浏览器。
from selenium import webdriver
import time
from selenium.webdriver.chrome.options import Options """
使用无头浏览器的基本配置
"""
chorme_options = Options()
chorme_options.add_argument("--headless")
chorme_options.add_argument("--disable-gpu") time.sleep(1)
bro = webdriver.Chrome(executable_path="./chromedriver.exe", chrome_options=chorme_options)
bro.get("https://www.baidu.com/")
time.sleep(1)
text_input = bro.find_element_by_id("kw")
value_btn = bro.find_element_by_id("su")
text_input.send_keys("玛莎拉斯")
value_btn.click()
time.sleep(1)
js = "window.scrollTo(0,document.body.scrollHeight)"
bro.execute_script(js) time.sleep(1)
page_text = bro.page_source
print(page_text)
bro.quit()
图片的懒加载技术
1 图片懒加载概念:
图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。
2 网站一般如何实现图片懒加载技术呢?
在网页源码中,在img标签中首先会使用一个“伪属性”(通常使用src2,original......)去存放真正的图片链接而并非是直接存放在src属性中。当图片出现到页面的可视化区域中,会动态将伪属性替换成src属性,完成图片的加载。
3 站长素材案例后续分析:通过细致观察页面的结构后发现,网页中图片的链接是存储在了src2这个伪属性中,代码如下:
from bs4 import BeautifulSoup
import requests # 爬取站长回家图片链接 http://sc.chinaz.com/tupian/meinvtupian.html url = "http://sc.chinaz.com/tupian/meinvtupian.html" headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36"
}
page = requests.get(url,headers=headers)
page.encoding = "utf8" soup = BeautifulSoup(page.text,"lxml") div_box = soup.find_all("div",id="container") for pic_box in div_box: src = pic_box.find_all("img")
for i in src:
print(i.attrs["alt"])
print(i.attrs["src"]) # 没有src属性, 直接报错
print(i.attrs["src2"]) # src2伪属性
爬虫-----selenium模块自动爬取网页资源的更多相关文章
- 一起学爬虫——使用Beautiful Soup爬取网页
要想学好爬虫,必须把基础打扎实,之前发布了两篇文章,分别是使用XPATH和requests爬取网页,今天的文章是学习Beautiful Soup并通过一个例子来实现如何使用Beautiful Soup ...
- 精通python网络爬虫之自动爬取网页的爬虫 代码记录
items的编写 # -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentati ...
- Python-异常处理 使用selenium库自动爬取数据
异常处理 处理程序的报错 语法 捕捉万能异常: try: print(a) except Exception as e: print("你的代码有问题") print(" ...
- python网络爬虫之使用scrapy自动爬取多个网页
前面介绍的scrapy爬虫只能爬取单个网页.如果我们想爬取多个网页.比如网上的小说该如何如何操作呢.比如下面的这样的结构.是小说的第一篇.可以点击返回目录还是下一页 对应的网页代码: 我们再看进入后面 ...
- python3爬取网页
爬虫 python3爬取网页资源方式(1.最简单: import'http://www.baidu.com/'print2.通过request import'http://www.baidu.com' ...
- Python爬虫初探 - selenium+beautifulsoup4+chromedriver爬取需要登录的网页信息
目标 之前的自动答复机器人需要从一个内部网页上获取的消息用于回复一些问题,但是没有对应的查询api,于是想到了用脚本模拟浏览器访问网站爬取内容返回给用户.详细介绍了第一次探索python爬虫的坑. 准 ...
- 一起学爬虫——使用selenium和pyquery爬取京东商品列表
layout: article title: 一起学爬虫--使用selenium和pyquery爬取京东商品列表 mathjax: true --- 今天一起学起使用selenium和pyquery爬 ...
- Python爬虫:为什么你爬取不到网页数据
前言: 之前小编写了一篇关于爬虫为什么爬取不到数据文章(文章链接为:Python爬虫经常爬不到数据,或许你可以看一下小编的这篇文章), 但是当时小编也是胡乱编写的,其实里面有很多问题的,现在小编重新发 ...
- python3爬虫爬取网页思路及常见问题(原创)
学习爬虫有一段时间了,对遇到的一些问题进行一下总结. 爬虫流程可大致分为:请求网页(request),获取响应(response),解析(parse),保存(save). 下面分别说下这几个过程中可以 ...
随机推荐
- 【Hibernate】Unable to locate appropriate constructor on class原因分析
通常我们喜欢将hql查询结果封装到POJO对象syntax:select new POJO(id,name) from POJO ; 这种封装需要POJO类提供对应构造器,POJO(id,name)构 ...
- iOS rebuild from bitcode对ipa大小的影响
https://developer.apple.com/library/content/technotes/tn2432/_index.html 为了测试一下rebuild from bitcode的 ...
- 使用DBMS_SHARED_POOL包将对象固定到共享池
使用DBMS_SHARED_POOL包将对象固定到共享池2011年06月24日 09:45:00 Leshami 阅读数:5808 版权声明:本文为博主原创文章,欢迎扩散,扩散请务必注明出处. htt ...
- vue——loading组件
<template> <div class="loading" :style="{height:loadingRadiusVal+'px',width: ...
- 金三银四背后,一个 Android 程序员的面试心得
回顾一下自己这段时间的经历,九月份的时候,公司通知了裁员,我匆匆忙忙地出去面了几家,但最终都没有拿到offer,我感觉今年的寒冬有点冷.到十二月份,公司开始第二波裁员,我决定主动拿赔偿走人.后续的面试 ...
- FM算法(二):工程实现
主要内容: 实现方法 Python实现FM算法 libFM 一.实现方法 1.FM模型函数 变换为线性复杂度的计算公式: 2.FM优化目标 根据不同的应用,FM可以采用不同的损失函数loss fu ...
- SpringBoot 请求参数后端校验
1.例如: package com.model.user; import com.model.PageEntity;import lombok.Getter;import lombok.Setter; ...
- C语言fread/fwrite填坑记
坑的描述 用fwrite把数据写入文件,再用fread读取,发现后半部分的数据可能是错的. 原因:原本要写入文件的数据中,有0x0A,如果用的是文本模式打开的文件流,在windows下0x0A会被转换 ...
- [方案]基于Zynq WiFi方案构建
基于Zynq系列,搭建无线传输平台 1) 2.4G 2) 5G AC
- Intervals 差分约束
题意:给定n个区间[Li,Ri]以及n个整数vi. 现在要有一个集合,使得这个集合和任意[Li,Ri]都有 至少 vi个元素相同. 问这个集合最少要几个元素. 定义S(x) 表示[1,x]中选择的元素 ...