码迷,mamicode.com
首页 > 编程语言 > 详细

python爬虫之selenium、phantomJs

时间:2019-04-21 12:44:20      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:正则表达   scripts   original   input   优化   dir   csr   节点   val   

图片懒加载技术

什么是图片懒加载技术

图片懒加载是一种网页优化技术。图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间。为了解决这种问题,通过前后端配合,使图片仅在浏览器当前视窗内出现时才加载该图片,达到减少首屏图片请求数的技术就被称为“图片懒加载”。

如何实现图片懒加载技术

在网页源码中,在img标签中首先会使用一个“伪属性”(通常使用src2,original......)去存放真正的图片链接而并非是直接存放在src属性中。当图片出现到页面的可视化区域中,会动态将伪属性替换成src属性,完成图片的加载。

如何破解图片懒加载技术

其实很简单,在对标签属性进行定位的时候,仔细观察它真正的属性进行提取。

例如:

import requests
from lxml import etree

def main():
    responses = requests.get(url=url, headers=headers)
    coding = responses.apparent_encoding
    responses.encoding = coding
    res_text = responses.text
    # 创建etree对象
    tree = etree.HTML(res_text)
    div_lst = tree.xpath(//div[@id="container"]/div)
    for one_div in div_lst:
        image_name = one_div.xpath(.//img/@alt)[0]
        image_url = one_div.xpath(.//img/@src2)
        print(image_name)
        print(image_url)

if __name__ == __main__:
    headers = {"User-Agent":Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0}
    url = http://sc.chinaz.com/tupian/gudianmeinvtupian.html
    main()

以上例子中就将src属性换为了src2属性。

selenium

1 什么是Selenium?

selenium是Python的一个第三方库,对外提供的接口可以操作浏览器,然后让浏览器完成自动化的操作。 
selenium最初是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。

2 前期准备

selenium安装就不再概述了

查看自己的谷歌浏览器版本

技术图片

查看自己对用的谷歌驱动: https://blog.csdn.net/huilan_same/article/details/51896672 

下载自己的谷歌驱动: http://chromedriver.storage.googleapis.com/index.html

这里我下载是:

技术图片

然后加压后把它放到python解释器的scripts目录中即可.

3 简单示例
from selenium import webdriver
from time import sleep

# 启动你的谷歌浏览
driver = webdriver.Chrome()
# 用get方法打开百度首页
driver.get(https://www.baidu.com)
# 找到第一个链接标签的文本并点击
driver.find_elements_by_link_text(设置)[0].click()
# 睡一秒
sleep(1)
# 找到搜索设置并点击
driver.find_elements_by_link_text(搜索设置)[0].click()
sleep(2)
# 找到id为nr的标签
ch = driver.find_element_by_id(nr)
sleep(1)
# 选择第3个标签点击
# ch.find_element_by_xpath(‘//*[@id="nr"]/option[3]‘).click()
ch.find_element_by_xpath(.//option[3]).click()
sleep(2)
# 保存设置
driver.find_elements_by_class_name("prefpanelgo")[0].click()
sleep(2)
# 处理弹出的警告
driver.switch_to_alert().accept()
sleep(2)
# 网搜索框里传入数据
driver.find_element_by_id(kw).send_keys(nba)
sleep(2)
# 点击搜索按钮
driver.find_element_by_id(su).click()
sleep(2)
# 关闭驱动
driver.close()
# 关闭浏览器
driver.quit()

这是一个设置百度搜索每个页面显示50条数据并搜索nba的程序

Selenium支持的浏览器非常多,如Chrome、Firefox、Edge等,还有Android、BlackBerry等手机端的浏览器。另外,也支持无界面浏览器PhantomJS,也就是后面要说的内容。

4 webdriver的元素定位
# 通过id属性
find_element_by_id()
# 通过name属性
find_element_by_name()
# 通过class的名字
find_element_by_class_name()
# 通过标签的名字
find_element_by_tag_name()
# 通过链接标签的文本
find_element_by_link_text()
# 通过链接标签的部分文本
find_element_by_partial_link_text()
# 通过xpath
find_element_by_xpath()
# 通过css选择器
find_element_by_css_selector()
注意:
1 find_element_by_xxx找的是第一个符合条件的标签,find_elements_by_xxx找的是所有符合条件的标签。
2 elenium还提供了通用方法find_element(),它需要传入两个参数:查找方式By和值。实际上,它就是find_element_by_id()
这种方法的通用函数版本,比如find_element_by_id(id)就等价于find_element(By.ID, id),二者得到的结果完全一致。
5 对节点进行交互
# 通过id知道输入框
input = browser.find_element_by_id(q)
# 向里面出入文本MAC
input.send_keys(MAC)
# 清楚文本框
input.clear()
# 再传入一个文本IPhone
input.send_keys(IPhone)
# 通过classname找到一个事件
button = browser.find_element_by_class_name(btn-search)
# 点击它
button.click()
6 动作链

什么是动作链呢?

在节点交互中,交互动作都是针对某个节点执行的。比如对于输入框,就调用它输入和清空的方法,对于按钮,就调用它点击的方法,其实还有一些操作,它们没有特定的执行对象,比如鼠标拖拽,键盘按键,它们使用另一种方式来执行,就是动作链。

以下例子演示了把一个节点从一处拖动到另一处:

from selenium import webdriver
from time import sleep
from selenium.webdriver import ActionChains

driver = webdriver.Chrome()
# 菜鸟教程的js演示代码
url = http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable
driver.get(url)
# 进入嵌套的页面
driver.switch_to.frame(iframeResult)
# 点位要拖动的标签
start = driver.find_element_by_css_selector(.ui-draggable)
# 拖动的目标标签
end = driver.find_element_by_css_selector(.ui-droppable)
# 创建一个鼠标事件
actions = ActionChains(driver)
# 点击要拖动的标签不松动
sleep(1)
actions.click_and_hold(start).perform()
# 然后移动到另一个标签
actions.move_to_element(end).perform()
# 往x轴移动40,y轴移动20
sleep(1)
actions.move_by_offset(xoffset=40, yoffset=20).perform()
# 释放动作
actions.release()

可能有人会对driver.switch_to.frame(‘iframeResult‘)这句代码有疑问

技术图片

技术图片

这个就是frame嵌套的。

在 web 应用中经常会出现 iframe 嵌套的应用,假设页面上有 A、B 两个 iframe,其中 B 在 A 内,那么定位 B 中的内容则需要先到 A,然后再到 B。

所以我们使用driver.switch_to.frame(‘iframeResult‘)直接进入嵌套的页面。

 7 执行js

有些api是selenium没有提供的,比如下拉进度条,但是可以通过吗模拟运行js来实现。

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get(https://www.jd.com/)
# 移动到页面最底部
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
sleep(2)
# 执行alert123这个代码 就是弹出123
driver.execute_script("alert(‘123‘)")

 这一块自动化测试用的挺多的,想学自动化测试的同学可以多学习下。

8 获取节点信息

通过page_source属性可以获取网页的源代码,接着就可以使用解析库(如正则表达式、Beautiful Soup、pyquery等)来提取信息了。

selenium自己也提供了提取节点信息的方法,如属性、文本等。这样的话,我们就可以不用通过解析源代码来提取信息了,非常方便。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as E
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
# 访问亚马逊首页
driver.get("https://www.amazon.cn/")
# 显示等待10秒
wait = WebDriverWait(driver, 10)
# 判断元素是否被加载到了dom中
wait.until(E.presence_of_element_located((By.ID,cc-lm-tcgShowImgContainer)))
# 通过选择器找到这个元素
tag=driver.find_element(By.CSS_SELECTOR,#cc-lm-tcgShowImgContainer img)
#获取标签属性,
print(tag.get_attribute(src))
#获取标签ID,位置,名称,大小(了解)
print(tag.id)
print(tag.location)
print(tag.tag_name)
print(tag.size)
driver.close()
9 延时等待

在selenium中,get()方法会在页面框加载结束后,结束执行。此时如果获得get_source,可能不是浏览器完全加载完成后的页面,某些额外的js,ajax可能不一定获取到,所以需要延时等待一下,确保节点加载出来了,这里等待的方式有2中:显式等待和隐式等待。

1 显式等待

上个例子就用到了显式等待,显式等待会设置一个固定的等待时间,但是实际情况是由于外界因素的影响,我们也不可能判断出需要多少时间,所有显示等待还有一种写法,如果在规定时间加载出了这个节点,就对这个节点进行操作,如果没有加载出,就抛出超时异常。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as E
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.get(https://www.baidu.com/)
input_tag = driver.find_element_by_id(kw)
input_tag.send_keys(美女)
# 模拟键盘回车键
input_tag.send_keys(Keys.ENTER)
# 创建一个显式等待
wait = WebDriverWait(driver, 10)
# 等待直到加载出content_left(content是左半区)
wait.until(E.presence_of_element_located((By.ID, content_left)))
content = driver.find_element(By.CSS_SELECTOR, "#content_left")
print(content)
driver.close()

如果将webDriverWait中的时间设置过低,会报错:

技术图片

2 隐式等待

当使用隐式等待执行测试的时候,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys


driver = webdriver.Chrome()
# 设置隐式等待
driver.implicitly_wait(10)
driver.get(https://www.baidu.com/)
input_tag = driver.find_element_by_id(kw)
input_tag.send_keys(NBA)
# 模拟键盘回车键
input_tag.send_keys(Keys.ENTER)
content = driver.find_element(By.CSS_SELECTOR, "#content_left")
print(content)
driver.close()
 10 cookie

使用selenium还可以对cookie进行操作,获取,添加,删除cookie:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get(https://www.zhihu.com/explore)
# 获取cookie
print(driver.get_cookies())
# 添加cookie
driver.add_cookie({name: name, domain: www.zhihu.com, value: germey})
print(driver.get_cookies())
# 删除cookie
driver.delete_all_cookies()
print(driver.get_cookies())
[{domain: .zhihu.com, httpOnly: False, name: l_n_c, path: /, secure: False, value: 1}, {domain: www.zhihu.com, expiry: 1555763561.220174, httpOnly: False, name: tgw_l7_route, path: /, secure: False, value: 537a925d07d06cecbf34cd06a153f671}, {domain: .zhihu.com, expiry: 1650370661.220268, httpOnly: False, name: q_c1, path: /, secure: False, value: 9ca2467feeaa4987a63360951034c876|1555762662000|1555762662000}, {domain: www.zhihu.com, httpOnly: False, name: _xsrf, path: /, secure: False, value: 270095e8c0bc05224a3eb61674d59ce0}, {domain: .zhihu.com, expiry: 1558354661.220341, httpOnly: False, name: r_cap_id, path: /, secure: False, value: "ZjhkMmMxZWE5NjlhNDY3OWE4ODA1NjI4MjhkYzc0Y2Y=|1555762662|257a989723432c66a22d10794cd998b22d419794"}, {domain: .zhihu.com, expiry: 1558354661.220391, httpOnly: False, name: cap_id, path: /, secure: False, value: "NTY2OWZiYmI2ODdlNDFkZWE1MzBiZTEyYTQ5MDFmYzk=|1555762662|5c5e5d6a7150c0da99f86af9d85cc63cafbea752"}, {domain: .zhihu.com, expiry: 1558354661.220438, httpOnly: False, name: l_cap_id, path: /, secure: False, value: "Njk2NWI1ZTIxYjg2NGZhZDhiOGJiYjM5ODg0Y2U2ZmM=|1555762662|6a4e7d4ab33c72012e5bf133ffadfe34aa88b8eb"}, {domain: .zhihu.com, httpOnly: False, name: n_c, path: /, secure: False, value: 1}, {domain: .zhihu.com, expiry: 1650370664.061236, httpOnly: False, name: d_c0, path: /, secure: False, value: "AJDm50C_Tg-PTkHkupcfIBQqf8xnPhGsu4M=|1555762665"}, {domain: .zhihu.com, expiry: 1633522664.358119, httpOnly: False, name: _xsrf, path: /, secure: False, value: mzatpYVVTALiHdu45yqz9q4yljxCPZ7n}, {domain: .zhihu.com, expiry: 1618834664, httpOnly: False, name: _zap, path: /, secure: False, value: ec95407d-3b81-4e43-81d5-277adf4b33b9}, {domain: .zhihu.com, expiry: 1618834664, httpOnly: False, name: __utma, path: /, secure: False, value: 51854390.2113439272.1555762665.1555762665.1555762665.1}, {domain: .zhihu.com, expiry: 1555764464, httpOnly: False, name: __utmb, path: /, secure: False, value: 51854390.0.10.1555762665}, {domain: .zhihu.com, httpOnly: False, name: __utmc, path: /, secure: False, value: 51854390}, {domain: .zhihu.com, expiry: 1571530664, httpOnly: False, name: __utmz, path: /, secure: False, value: 51854390.1555762665.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)}, {domain: .zhihu.com, expiry: 1618834664, httpOnly: False, name: __utmv, path: /, secure: False, value: 51854390.000--|3=entry_date=20190420=1}]
[{domain: .zhihu.com, httpOnly: False, name: l_n_c, path: /, secure: False, value: 1}, {domain: www.zhihu.com, expiry: 1555763561.220174, httpOnly: False, name: tgw_l7_route, path: /, secure: False, value: 537a925d07d06cecbf34cd06a153f671}, {domain: .zhihu.com, expiry: 1650370661.220268, httpOnly: False, name: q_c1, path: /, secure: False, value: 9ca2467feeaa4987a63360951034c876|1555762662000|1555762662000}, {domain: www.zhihu.com, httpOnly: False, name: _xsrf, path: /, secure: False, value: 270095e8c0bc05224a3eb61674d59ce0}, {domain: .zhihu.com, expiry: 1558354661.220341, httpOnly: False, name: r_cap_id, path: /, secure: False, value: "ZjhkMmMxZWE5NjlhNDY3OWE4ODA1NjI4MjhkYzc0Y2Y=|1555762662|257a989723432c66a22d10794cd998b22d419794"}, {domain: .zhihu.com, expiry: 1558354661.220391, httpOnly: False, name: cap_id, path: /, secure: False, value: "NTY2OWZiYmI2ODdlNDFkZWE1MzBiZTEyYTQ5MDFmYzk=|1555762662|5c5e5d6a7150c0da99f86af9d85cc63cafbea752"}, {domain: .zhihu.com, expiry: 1558354661.220438, httpOnly: False, name: l_cap_id, path: /, secure: False, value: "Njk2NWI1ZTIxYjg2NGZhZDhiOGJiYjM5ODg0Y2U2ZmM=|1555762662|6a4e7d4ab33c72012e5bf133ffadfe34aa88b8eb"}, {domain: .zhihu.com, httpOnly: False, name: n_c, path: /, secure: False, value: 1}, {domain: .zhihu.com, expiry: 1650370664.061236, httpOnly: False, name: d_c0, path: /, secure: False, value: "AJDm50C_Tg-PTkHkupcfIBQqf8xnPhGsu4M=|1555762665"}, {domain: .zhihu.com, expiry: 1633522664.358119, httpOnly: False, name: _xsrf, path: /, secure: False, value: mzatpYVVTALiHdu45yqz9q4yljxCPZ7n}, {domain: .zhihu.com, expiry: 1618834664, httpOnly: False, name: _zap, path: /, secure: False, value: ec95407d-3b81-4e43-81d5-277adf4b33b9}, {domain: .zhihu.com, expiry: 1618834664, httpOnly: False, name: __utma, path: /, secure: False, value: 51854390.2113439272.1555762665.1555762665.1555762665.1}, {domain: .zhihu.com, expiry: 1555764464, httpOnly: False, name: __utmb, path: /, secure: False, value: 51854390.0.10.1555762665}, {domain: .zhihu.com, httpOnly: False, name: __utmc, path: /, secure: False, value: 51854390}, {domain: .zhihu.com, expiry: 1571530664, httpOnly: False, name: __utmz, path: /, secure: False, value: 51854390.1555762665.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)}, {domain: .zhihu.com, expiry: 1618834664, httpOnly: False, name: __utmv, path: /, secure: False, value: 51854390.000--|3=entry_date=20190420=1}, {domain: www.zhihu.com, expiry: 2186482664, httpOnly: False, name: name, path: /, secure: True, value: germey}]
[]
 11 异常处理
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchFrameException

try:
    driver = webdriver.Chrome()
    driver.get(http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable)
    driver.switch_to.frame(iframssseResult)
except TimeoutException as e:
    print(e)
except NoSuchFrameException as e:
    print(e)
finally:
    driver.close()

超时等待哪里就可以这样写。

phantomJs

phantomJs是一款无界面的浏览器,其自动化操作流程和上面的谷歌浏览器是一致的。

由于是无界面的,为了能够展示自动化操作流程,PhantomJS为用户提供了一个截屏的功能,使用save_screenshot函数实现。

from selenium import webdriver
import time

# exe路径
path = rC:\phantomjs-2.1.1-windows\bin\phantomjs.exe
driver = webdriver.PhantomJS(path)
driver.get("https://www.baidu.com")
time.sleep(2)
driver.save_screenshot(rbaidu.png)
my_input = driver.find_element_by_id(kw)
my_input.send_keys(nba)
driver.save_screenshot(rnba.png)
# 查找搜索按钮
button = driver.find_elements_by_class_name(s_btn)[0].click()
time.sleep(3)
driver.save_screenshot(rshow.png)
driver.close()
driver.quit()

 使用selenum+phantomJs可以解决某些网页js动态加载问题。

selenium+phantomJs爬取豆瓣电影的电影信息

 首先来看下这个页面:https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action=

技术图片

查看他的网页源代码:发现它是js动态加载显示的

from selenium import webdriver
import time

def main():
    path = rC:\phantomjs-2.1.1-windows\bin\phantomjs.exe
    driver = webdriver.PhantomJS(path)
    driver.get(url)
    time.sleep(2)
    driver.save_screenshot(r1.png)
    driver.execute_script(window.scrollTo(0,document.body.scrollHeight))
    time.sleep(2)
    driver.save_screenshot(2.png)
    time.sleep(1)
    html_source = driver.page_source
    with open(source.html, w, encoding=utf-8) as  f:
        f.write(html_source)
    driver.quit()

if __name__ == "__main__":
    url = https://movie.douban.com/typerank?type_name=%E6%81%90%E6%80%96&type=20&interval_id=100:90&action=
    main()

这样就可以拿到它的源码了:

技术图片

谷歌无头浏览器 Headless Chrome

由于phantomJs已经停止了更新和维护,所以推荐使用谷歌的无头浏览器,这是一款无界面的谷歌浏览器

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep

# 创建一个无头浏览器对象
chrome_options = Options()
# 设置它为无框模式
chrome_options.add_argument(--headless)
# 如果在windows上运行需要加代码
chrome_options.add_argument(--disable-gpu)

browser = webdriver.Chrome(chrome_options=chrome_options)
browser.get(https://www.baidu.com/)
sleep(2)
browser.save_screenshot(first_page.png)
browser.quit()
 使用谷歌无头浏览器爬取网易新闻的国内模块

单独写了一篇博客:https://www.cnblogs.com/xiaozx/p/10744604.html

python爬虫之selenium、phantomJs

标签:正则表达   scripts   original   input   优化   dir   csr   节点   val   

原文地址:https://www.cnblogs.com/xiaozx/p/10738129.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!