python爬虫之seleniumphantomJs

Posted 噼里巴啦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python爬虫之seleniumphantomJs相关的知识,希望对你有一定的参考价值。

图片懒加载技术

什么是图片懒加载技术

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

如何实现图片懒加载技术

在网页源码中,在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\', 08.Python网络爬虫之图片懒加载技术selenium和PhantomJS

爬虫之图片懒加载技术selenium和PhantomJS

07-seleniumPhantomJS(无头浏览器)

.net下使用SeleniumPhantomJS

Python爬虫之使用celery加速爬虫

python爬虫之基础学习