一 . 图片懒加载技术
案例分析:抓取站长素材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了