爬虫之图片懒加载技术,selenium

 

一 . 图片懒加载技术

  案例分析:抓取站长素材http://sc.chinaz.com/中的图片数据

import requests
from lxml import etree

if __name__ == "__main__":
     url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html'
     headers = {
         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) \
        Chrome/69.0.3497.100 Safari/537.36
', } #获取页面文本数据 response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析页面数据(获取页面中的图片链接) #创建etree对象 tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析获取图片地址和图片的名称 for div in div_list: image_url = div.xpath('.//img/@src') image_name = div.xpath('.//img/@alt') print(image_url) #打印图片链接 # print(image_name)#打印图片名称

  运行结果发现,我们可以获取到图片名称,但是获取到的链接为空,这就是图片懒加载的原因

  图片懒加载的概念:

图片懒加载是一种网页优化技术,当你请求网页的时候,如果所有图片一下全加载出来会影响网页加载效率的,
为了解决这个问题,前后端协同工作,使图片在浏览器当前窗口才加载出来,达到减少首屏图片请求次数,这种就称为图片懒加载

  网站一般实现图片懒加载的技术

在网页源码中,在img标签中首先会使用这个'伪属性'(通常使用src2,original...)去存放真正的链接,
当图片出现到可视化窗口的时候,会动态的替换成src属性,完成图片加载

  通过细致观察页面的结构后发现,网页中图片的链接是存储在了src2这个伪属性中

import requests
from lxml import etree

if __name__ == "__main__":
     url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html'
     headers = {
         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) \
        Chrome/69.0.3497.100 Safari/537.36
', } #获取页面文本数据 response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析页面数据(获取页面中的图片链接) #创建etree对象 tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析获取图片地址和图片的名称 for div in div_list: image_url = div.xpath('.//img/@src2') #src2伪属性 image_name = div.xpath('.//img/@alt') print(image_url) #打印图片链接 print(image_name)#打印图片名称

二 . selenium

  为什么要使用selenium?

有些网站的数据是动态加载的,如果用requests是不能获取到数据的,用selenium通过驱动浏览器,完全模拟浏览器操作,比如下拉,单击,跳转等,这样就可以获取到数据

  环境安装

下载安装selenium:pip install selenium
下载浏览器驱动程序:
http://chromedriver.storage.googleapis.com/index.html
查看驱动和浏览器版本的映射关系:
http://blog.csdn.net/huilan_same/article/details/51896672

  操作前需要知道的知识

# 元素定位
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()

  简单使用与效果展示

from selenium import webdriver
from time import sleep

# 后面是你的浏览器驱动位置,记得前面加r'','r'是防止字符转义的
driver = webdriver.Chrome(r'驱动程序路径')
# 用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()
sleep(2)
# 在打开的页面中找到“Selenium - 开源中国社区”,并打开这个页面
driver.find_elements_by_link_text('美女_百度图片')[0].click()
sleep(3)

# 关闭浏览器
driver.quit()

  上述的class和id都是通过网页源代码找到的

  -- 来一个有常用的功能简易版使用

from selenium import webdriver
from time import sleep
# 使用谷歌浏览器,填写浏览器驱动位置
driver = webdriver.Chrome(r'./chromedriver.exe')
# 打开网址用get
bro = driver.get('http://www.baidu.com')
sleep(2)
# 找到搜索框的id
content_input = driver.find_element_by_id('kw')
# 输入内容
content_input.send_keys('库里')
sleep(2)
# 清空用clear() # content_input.clear()
#
找到搜索按钮的id btn = driver.find_element_by_id('su') btn.click() sleep(3) # 退出 driver.quit()

  执行js代码

from selenium import webdriver
from time import sleep
# 使用谷歌浏览器,填写浏览器驱动位置
driver = webdriver.Chrome(r'./chromedriver.exe')
driver.get('https://xueqiu.com')
sleep(3)

# 实现滚轮向下滑动,第一个参数是横向滚轮,第二个参数是纵向
js = 'window.scrollTo(0,document.body.scrollHeight)'
# 执行js代码
driver.execute_script(js)
sleep(2)
# 每执行一次就向下滑动一下
driver.execute_script(js)
sleep(2)

# 这样就能获取到动态加载的数据了
print(driver.page_source)
# 退出
driver.quit()

   谷歌无头浏览器,是一款无界面的谷歌浏览器

# 谷歌无头浏览器,不出现可视化界面
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from time import sleep

# 创建一个参数对象,用来控制chrome以无界面模式打开
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

# 使用谷歌浏览器,填写浏览器驱动位置
browser = webdriver.Chrome(executable_path=r'./chromedriver.exe', options=chrome_options)
# 打开网址用get
bro = browser.get('http://www.baidu.com')
sleep(2)
# 找到搜索框的id
content_input = browser.find_element_by_id('kw')
# 输入内容
content_input.send_keys('库里')
sleep(2)
# 找到搜索按钮的id
btn = browser.find_element_by_id('su')
btn.click()
sleep(3)

# 截屏,没啥意义
# browser.save_screenshot('./curry.png')

# 退出
browser.quit()

  向前和后退

import time
from selenium import webdriver
 
browser=webdriver.Chrome(r'./chromedriver.exe')
browser.get('https://www.baidu.com')
browser.get('https://www.taobao.com')
browser.get('http://www.sina.com.cn/')
 
browser.back()
time.sleep(2)
browser.forward()
time.sleep(2)
browser.close()

  动作链(鼠标拖拽,键盘按键,这些动作的执行就是动作链)

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)
# 当定位标签存在iframe的时候需要用到switch_to
browser.switch_to.frame('iframeResult')  # 里面是id
# 初识位置
source = browser.find_element_by_id('#draggable')
# 结束位置
target = browser.find_element_by_id('#droppable')
# 创建一个动作链的对象
action = ActionChains(browser)
action.drag_and_drop(source,target)
# 执行动作链
aciton.perform()
sleep(3)

# 可以模拟人的拖动效果,慢慢的拖动
# 点击长按
# actions.click_and_hold(source)
# time.sleep(3)
# for i in range(5):
#     # perform表示开始执行动作链
#     action.move_by_offset(xoffset=17,yoffset=0).perform()
#     time.sleep(0.5)

browser.quit()

  selenium规避检测

现在不少大网站有对selenium采取了监测机制。比如正常情况下我们用浏览器访问淘宝等网站的 window.navigator.webdriver的值为 undefined。
而使用selenium访问则该值为true。

  解决办法

from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions

option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(r'浏览器驱动程序路径',options=option)

# 其他操作不用变,再去console一下window.navigator.webdriver就显示undefined了

 

 

posted @ 2019-05-18 14:52  一个很善良的抱爱  阅读(1161)  评论(0编辑  收藏  举报