Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 欧美日本高清一本二本三本,亚洲一区中文,中文字幕先锋影音

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          抖音上很火的3D立體動態相冊實現代碼!趕快學起來吧

          言:

          圣誕節快到了,是不是要給女朋友或者正在追求的妹子一點小驚喜呢,今天這篇博客就分享下前端代碼如何實現3D立體動態相冊。趕緊學會了,來制作屬于我們程序員的浪漫吧!先上效果圖,來引起下你們的興趣。

          正文:

          一、新建一個index.html的文件,代碼如下

          <!DOCTYPE html>
          <html lang="en">
          <head>
          <meta charset="UTF-8">
          <title>純CSS實現鼠標經過3D立體動態展示圖片特效代碼</title>
          <link type="text/css" href="css/style.css" rel="stylesheet" />
          </head>
          <body>
          <div class="box">
          	<ul class="minbox">
          		<li></li>
          		<li></li>
          		<li></li>
          		<li></li>
          		<li></li>
          		<li></li>
          	</ul>
          	<ol class="maxbox">
          		<li></li>
          		<li></li>
          		<li></li>
          		<li></li>
          		<li></li>
          		<li></li>
          	</ol>
          </div>
          </body>
          </html>

          二、css樣式的代碼

          @charset "utf-8";
          *{
          	margin:0;
          	padding:0;
          }
          body{
          	max-width: 100%;
          	min-width: 100%;
          	height: 100%;
          	background-size: cover;
          	background-repeat: no-repeat;
          	background-attachment: fixed;
          	background-size:100% 100%;
          	position: absolute;
          	margin-left: auto;
          	margin-right: auto;
          }
          li{
          	list-style: none;
          }
          .box{
          	width:200px;
          	height:200px;
          	background-size: cover;
          	background-repeat: no-repeat;
          	background-attachment: fixed;
          	background-size:100% 100%;
          	position: absolute;
          	margin-left: 42%;
          	margin-top: 22%;
          	-webkit-transform-style:preserve-3d;
          	-webkit-transform:rotateX(13deg);
          	-webkit-animation:move 5s linear infinite;
          }
          .minbox{
          	width:100px;
          	height:100px;
          	position: absolute;
          	left:50px;
          	top:30px;
          	-webkit-transform-style:preserve-3d;
          }
          .minbox li{
          	width:100px;
          	height:100px;
          	position: absolute;
          	left:0;
          	top:0;
          }
          .minbox li:nth-child(1){
          	background: url(../img/01.png) no-repeat 0 0;
          	-webkit-transform:translateZ(50px);
          }
          .minbox li:nth-child(2){
          	background: url(../img/02.png) no-repeat 0 0;
          	-webkit-transform:rotateX(180deg) translateZ(50px);
          }
          .minbox li:nth-child(3){
          	background: url(../img/03.png) no-repeat 0 0;
          	-webkit-transform:rotateX(-90deg) translateZ(50px);
          }
          .minbox li:nth-child(4){
          	background: url(../img/04.png) no-repeat 0 0;
          	-webkit-transform:rotateX(90deg) translateZ(50px);
          }
          .minbox li:nth-child(5){
          	background: url(../img/05.png) no-repeat 0 0;
          	-webkit-transform:rotateY(-90deg) translateZ(50px);
          }
          .minbox li:nth-child(6){
          	background: url(../img/06.png) no-repeat 0 0;
          	-webkit-transform:rotateY(90deg) translateZ(50px);
          }
          .maxbox li:nth-child(1){
          	background: url(../img/1.png) no-repeat 0 0;
          	-webkit-transform:translateZ(50px);
          }
          .maxbox li:nth-child(2){
          	background: url(../img/2.png) no-repeat 0 0;
          	-webkit-transform:translateZ(50px);
          }
          .maxbox li:nth-child(3){
          	background: url(../img/3.png) no-repeat 0 0;
          	-webkit-transform:rotateX(-90deg) translateZ(50px);
          }
          .maxbox li:nth-child(4){
          	background: url(../img/4.png) no-repeat 0 0;
          	-webkit-transform:rotateX(90deg) translateZ(50px);
          }
          .maxbox li:nth-child(5){
          	background: url(../img/5.png) no-repeat 0 0;
          	-webkit-transform:rotateY(-90deg) translateZ(50px);
          }
          .maxbox li:nth-child(6){
          	background: url(../img/6.png) no-repeat 0 0;
          	-webkit-transform:rotateY(90deg) translateZ(50px);
          }
          .maxbox{
          	width: 800px;
          	height: 400px;
          	position: absolute;
          	left: 0;
          	top: -20px;
          	-webkit-transform-style: preserve-3d;
          	
          }
          .maxbox li{
          	width: 200px;
          	height: 200px;
          	background: #fff;
          	border:1px solid #ccc;
          	position: absolute;
          	left: 0;
          	top: 0;
          	opacity: 0.2;
          	-webkit-transition:all 1s ease;
          }
          .maxbox li:nth-child(1){
          	-webkit-transform:translateZ(100px);
          }
          .maxbox li:nth-child(2){
          	-webkit-transform:rotateX(180deg) translateZ(100px);
          }
          .maxbox li:nth-child(3){
          	-webkit-transform:rotateX(-90deg) translateZ(100px);
          }
          .maxbox li:nth-child(4){
          	-webkit-transform:rotateX(90deg) translateZ(100px);
          }
          .maxbox li:nth-child(5){
          	-webkit-transform:rotateY(-90deg) translateZ(100px);
          }
          .maxbox li:nth-child(6){
          	-webkit-transform:rotateY(90deg) translateZ(100px);
          }
          .box:hover ol li:nth-child(1){
          	-webkit-transform:translateZ(300px);
          	width: 400px;
          	height: 400px;
          	opacity: 0.8;
          	left: -100px;
          	top: -100px;
          }
          .box:hover ol li:nth-child(2){
          	-webkit-transform:rotateX(180deg) translateZ(300px);
          	width: 400px;
          	height: 400px;
          	opacity: 0.8;
          	left: -100px;
          	top: -100px;
          }
          .box:hover ol li:nth-child(3){
          	-webkit-transform:rotateX(-90deg) translateZ(300px);
          	width: 400px;
          	height: 400px;
          	opacity: 0.8;
          	left: -100px;
          	top: -100px;
          }
          .box:hover ol li:nth-child(4){
          	-webkit-transform:rotateX(90deg) translateZ(300px);
          	width: 400px;
          	height: 400px;
          	opacity: 0.8;
          	left: -100px;
          	top: -100px;
          }
          .box:hover ol li:nth-child(5){
          	-webkit-transform:rotateY(-90deg) translateZ(300px);
          	width: 400px;
          	height: 400px;
          	opacity: 0.8;
          	left: -100px;
          	top: -100px;
          }
          .box:hover ol li:nth-child(6){
          	-webkit-transform:rotateY(90deg) translateZ(300px);
          	width: 400px;
          	height: 400px;
          	opacity: 0.8;
          	left: -100px;
          	top: -100px;
          }
          @keyframes move{
          	0%{
          		-webkit-transform: rotateX(13deg) rotateY(0deg);
          	}
          	100%{
          		-webkit-transform:rotateX(13deg) rotateY(360deg);
          	}
          }

          三、文件的目錄結構,把css文件放到css文件夾里,圖片放到img文件夾里。

          四、圖片尺寸不會修改的,可以選擇使用美圖秀秀網頁版很簡單

          五、容易出現的問題 ,圖片展示不全或展示的方向不對

          1.圖片尺寸需要修改 (解決展示不全的情況)

          上圖是我的圖片文件夾里放的圖片 ,首先01-06編號命名的圖片尺寸是100x100px的大小的,1-6編號是400x400px,如果效果想展示最佳,100x100px的圖片是以頭部特寫的照片最好,因為01-06是立體照片內部小正方體的照片,1-6編號是外部正方體的照片。

          2.圖片的方向需要修改(解決頭朝下的問題)

          修改的方向如上圖展示所示,比如第三張頭就應該朝下,否則形成的效果圖像會出現頭是倒著的情況。

          六、放一下動態效果圖

          總結:

          生活雖然總有辛酸,但是我們不應該減少去創造生活的樂趣,不斷尋找屬于自己的那份快樂,才應該是我們生活的態度。

          我自己是一名從事了多年開發的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年年初我花了一個月整理了一份最適合2019年學習的web前端學習干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關注我的頭條號并在后臺私信我:前端,即可免費獲取。

          原文鏈接:https://blog.csdn.net/jdk_wangtaida/article/details/103253883

          析QQ空間

          登錄QQ空間

          爬取第一步,分析站點,首先需要知道如何登錄QQ空間。最初想法是用requests庫配置登錄請求,模擬登錄,但是不久便放棄了這一思路,請看下圖↓

          login

          根據登錄按鈕綁定的監聽事件可以追蹤到該按鈕的點擊事件如下:

          login function

          賬號加密是必然的,但這一堆堆的代碼真心不好解析,有耐心的勇士盡情一試!

          在排除這種登錄方法后,選擇selenium模擬用戶登錄不失為省時省力的方法,而且我們只是需要通過selenium完成登錄,獲取到Cookies和后面講述的g_tk參數后,就可以停用了,所以效率并不太低。

          分析空間相冊

          登錄以后,頁面會跳轉至 [https://user.qzone.qq.com/{QQ_NUMBER}](javascript:;), 這時把鼠標移到導航欄你會發現,所有的導航欄鏈接都是javascript:; 。沒錯就是這么坑,一切都是暗箱操作。

          當然這并不難處理,使用調試工具捕獲點擊后產生的請求,然后過濾出正確的請求包即可。因為網絡包非常多,那么怎么過濾呢,猜想相冊數據的API必然會返回個列表list,嘗試過濾list然后逐個排除,最后定位到請求包。下面是通過fcg_list過濾后的數據包,列表信息以jsonp格式返回,稍作處理即可當做json格式來讀?。ê竺嬗兄v)。

          album list

          從Headers和Response可以分別獲取到兩組重要信息:

          1. request 獲取相冊列表所需的請求信息,包括請求鏈接和參數
          2. response 數據包包含的所有相冊的信息,是每個相冊所含照片對應的請求包參數的數據來源

          先看請求包:

          # url
          https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3
          
          # args
          g_tk: 477819917
          callback: shine0_Callback
          t: 691481346
          hostUin: 123456789
          uin: 123456789
          appid: 4
          inCharset: utf-8
          outCharset: utf-8
          source: qzone
          plat: qzone
          format: jsonp
          notice: 0
          filter: 1
          handset: 4
          pageNumModeSort: 40
          pageNumModeClass: 15
          needUserInfo: 1
          idcNum: 4
          callbackFun: shine0
          _: 1551788226819
          

          其中hostUin, uin都是QQ號,g_tk是必須的且每次重新登錄都會更新(后面有講如何獲?。渌行﹨挡皇潜仨毜?,我嘗試后整理出如下請求參數:

          query = {
           'g_tk': self.g_tk,
           'hostUin': self.username,
           'uin': self.username,
           'appid': 4,
           'inCharset': 'utf-8',
           'outCharset': 'utf-8',
           'source': 'qzone',
           'plat': 'qzone',
           'format': 'jsonp'
          }
          

          接下來看jsonp格式的跨域響應包:

          shine0_Callback({
           "code":0,
           "subcode":0,
           "message":"",
           "default":0,
           "data":
          {
           "albumListModeSort" : [
           {
           "allowAccess" : 1,
           "anonymity" : 0,
           "bitmap" : "10000000",
           "classid" : 106,
           "comment" : 11,
           "createtime" : 1402661881,
           "desc" : "",
           "handset" : 0,
           "id" : "V13LmPKk0JLNRY",
           "lastuploadtime" : 1402662103,
           "modifytime" : 1408271987,
           "name" : "畢業季",
           "order" : 0,
           "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA",
           "priv" : 1,
           "pypriv" : 1,
           "total" : 4,
           "viewtype" : 0
           },
          

          shine0_Callback是請求包的callbackFun參數決定的,如果沒這個參數,響應包會以_Callback作為默認名,當然這都不重要。所有相冊信息以json格式存入albumListModeSort中,上面僅截取了一個相冊的信息。

          相冊信息中,name代表相冊名稱,id作為唯一標識可用于請求該相冊內的照片信息,而pre僅僅是一個預覽縮略圖的鏈接,無關緊要。

          分析單個相冊

          與獲取相冊信息類似,進入某一相冊,使用cgi_list過濾數據包,找到該相冊的照片信息

          photo list

          同樣的道理,根據數據包可以獲取照片列表信息的請求包和響應信息,先看請求:

          # url
          https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo
          
          # args
          g_tk: 477819917
          callback: shine0_Callback
          t: 952444063
          mode: 0
          idcNum: 4
          hostUin: 123456789
          topicId: V13LmPKk0JLNRY
          noTopic: 0
          uin: 123456789
          pageStart: 0
          pageNum: 30
          skipCmtCount: 0
          singleurl: 1
          batchId: 
          notice: 0
          appid: 4
          inCharset: utf-8
          outCharset: utf-8
          source: qzone
          plat: qzone
          outstyle: json
          format: jsonp
          json_esc: 1
          question: 
          answer: 
          callbackFun: shine0
          _: 1551790719497
          

          其中有幾個關鍵參數:

          1. g_tk - 與相冊列表參數一致
          2. topicId - 與相冊列表參數中的id一致
          3. pageStart - 本次請求照片的起始編號
          4. pageNum - 本次請求的照片數量

          為了一次性獲取所有照片,可以將pageStart設為0,pageNum設為所有相冊所含照片的最大值。

          同樣可以對上面的參數進行簡化,在相冊列表請求參數的基礎上添加topicId,pageStart和pageNum三個參數即可。

          下面來看返回的照片列表信息:

          shine0_Callback({
           "code":0,
           "subcode":0,
           "message":"",
           "default":0,
           "data":
          {
           "limit" : 0,
           "photoList" : [
           {
           "batchId" : "1402662093402000",
           "browser" : 0,
           "cameratype" : " ",
           "cp_flag" : false,
           "cp_x" : 455,
           "cp_y" : 388,
           "desc" : "",
           "exif" : {
           "exposureCompensation" : "",
           "exposureMode" : "",
           "exposureProgram" : "",
           "exposureTime" : "",
           "flash" : "",
           "fnumber" : "",
           "focalLength" : "",
           "iso" : "",
           "lensModel" : "",
           "make" : "",
           "meteringMode" : "",
           "model" : "",
           "originalTime" : ""
           },
           "forum" : 0,
           "frameno" : 0,
           "height" : 621,
           "id" : 0,
           "is_video" : false,
           "is_weixin_mode" : 0,
           "ismultiup" : 0,
           "lloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!",
           "modifytime" : 1402661792,
           "name" : "QQ圖片20140612104616",
           "origin" : 0,
           "origin_upload" : 0,
           "origin_url" : "",
           "owner" : "123456789",
           "ownername" : "123456789",
           "photocubage" : 91602,
           "phototype" : 1,
           "picmark_flag" : 0,
           "picrefer" : 1,
           "platformId" : 0,
           "platformSubId" : 0,
           "poiName" : "",
           "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/a\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!",
           "raw" : "http:\/\/r.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/r\/dIY29GUbJgAA",
           "raw_upload" : 1,
           "rawshoottime" : 0,
           "shoottime" : 0,
           "shorturl" : "",
           "sloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!",
           "tag" : "",
           "uploadtime" : "2014-06-13 20:21:33",
           "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/b\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!",
           "width" : 932,
           "yurl" : 0
           },
           // ...
           ]
           "t" : "952444063",
           "topic" : {
           "bitmap" : "10000000",
           "browser" : 0,
           "classid" : 106,
           "comment" : 1,
           "cover_id" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!",
           "createtime" : 1402661881,
           "desc" : "",
           "handset" : 0,
           "id" : "V13LmPKk0JLNRY",
           "is_share_album" : 0,
           "lastuploadtime" : 1402662103,
           "modifytime" : 1408271987,
           "name" : "畢業季",
           "ownerName" : "707922098",
           "ownerUin" : "707922098",
           "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA",
           "priv" : 1,
           "pypriv" : 1,
           "share_album_owner" : 0,
           "total" : 4,
           "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/b\/dIY29GUbJgAA",
           "viewtype" : 0
           },
           "totalInAlbum" : 4,
           "totalInPage" : 4
          }
          

          返回的照片信息都存于photoList, 上面同樣只截取了一張照片的信息,后面一部分返回的是當前相冊的一些基本信息。totalInAlbum, totalInPage存儲了當前相冊總共包含的照片數及本次返回的照片數。而我們需要下載的圖片鏈接則是url!

          OK, 到此,所有請求和響應數據都分析清楚了,接下來便是coding的時候了。

          確定爬取方案

          1. 創建qqzone類,初始化用戶信息
          2. 使用Selenium模擬登錄
          3. 獲取Cookies和g_tk
          4. 使用requests獲取相冊列表信息
          5. 遍歷相冊,獲取照片列表信息并下載照片

          創建qqzone類

          class qqzone(object):
           """QQ空間相冊爬蟲"""
           def __init__(self, user):
           self.username = user['username']
           self.password = user['password']
          

          模擬登錄

          from selenium import webdriver
          from selenium.webdriver.common.keys import Keys
          from selenium.common.exceptions import WebDriverExceptio
          
          # ...
          
          def _login_and_get_args(self):
           """登錄QQ,獲取Cookies和g_tk"""
           opt = webdriver.ChromeOptions()
           opt.set_headless()
          
           driver = webdriver.Chrome(chrome_options=opt)
           driver.get('https://i.qq.com/')
           # time.sleep(2)
          
           logging.info('User {} login...'.format(self.username))
           driver.switch_to.frame('login_frame')
           driver.find_element_by_id('switcher_plogin').click()
           driver.find_element_by_id('u').clear()
           driver.find_element_by_id('u').send_keys(self.username)
           driver.find_element_by_id('p').clear()
           driver.find_element_by_id('p').send_keys(self.password)
           driver.find_element_by_id('login_button').click()
          
           time.sleep(1)
           driver.get('https://user.qzone.qq.com/{}'.format(self.username))
          

          此處需要注意的是:

          1. 使用selenium需要安裝對應的webdriver
          2. 可以通過webdriver.Chrome()指定瀏覽器位置,否則默認從環境變量定義的路徑查找
          3. 如果電腦打開瀏覽器較慢,可能需要在driver.get后sleep幾秒

          獲取 Cookies

          使用selenium獲取Cookies非常方便

          self.cookies = driver.get_cookies()
          

          獲取 g_tk

          獲取g_tk最開始可以說是本爬蟲最大的難點,因為從網頁中根本找不到直接寫明的數值,只有各種函數調用。為此我全局搜索,發現好多地方都有其獲取方式。

          g_tk

          最后選擇了其中一處,通過selenium執行腳本的功能成功獲取到了g_tk!

          self.g_tk = driver.execute_script('return QZONE.FP.getACSRFToken()')
          

          到此,selenium的使命就完成了,剩下的將通過requests來完成。

          初始化 request.Session

          接下來需要逐步生成請求然后獲取數據。但是為方便起見,這里使用會話的方式請求數據,配置好cookie和headers,省的每次請求都設置一遍。

          def _init_session(self):
           self.session = requests.Session()
           for cookie in self.cookies:
           self.session.cookies.set(cookie['name'], cookie['value'])
           self.session.headers = {
           'Referer': 'https://qzs.qq.com/qzone/photo/v7/page/photo.html?init=photo.v7/module/albumList/index&navBar=1',
           'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'
           }
          

          請求相冊信息

          獲取相冊信息,需要先封裝好請求參數,然后通過session.get爬取數據,再通過正則匹配以json格式讀取jsonp數據,最后解析所需的name和id。

          def _get_ablum_list(self):
           """獲取相冊的列表信息"""
           album_url = '{}{}'.format(
           'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3?',
           self._get_query_for_request())
          
           logging.info('Getting ablum list id...')
           resp = self.session.get(album_url)
           data = self._load_callback_data(resp)
          
           album_list = {}
           for item in data['data']['albumListModeSort']:
           album_list[item['name']] = item['id']
          
           return album_list
          

          其中的參數組合來自下面的函數_get_query_for_request函數。

          def _get_query_for_request(self, topicId=None, pageStart=0, pageNum=100):
           """獲取請求相冊信息或照片信息所需的參數
          
           Args:
           topicId: 每個相冊對應的唯一標識符
           pageStart: 請求某個相冊的照片列表信息所需的起始頁碼
           pageNum: 單次請求某個相冊的照片數量
          
           Returns:
           一個組合好所有請求參數的字符串
           """
           query = {
           'g_tk': self.g_tk,
           'hostUin': self.username,
           'uin': self.username,
           'appid': 4,
           'inCharset': 'utf-8',
           'outCharset': 'utf-8',
           'source': 'qzone',
           'plat': 'qzone',
           'format': 'jsonp'
           }
           if topicId:
           query['topicId'] = topicId
           query['pageStart'] = pageStart
           query['pageNum'] = pageNum
           return '&'.join('{}={}'.format(key, val) for key, val in query.items())
          

          其中的jsonp解析函數如下,主體部分就是一個正則匹配,非常簡單。

          def _load_callback_data(self, resp):
           """以json格式解析返回的jsonp數據"""
           try:
           resp.encoding = 'utf-8'
           data = loads(re.search(r'.*?\(({.*}).*?\).*', resp.text, re.S)[1])
           return data
           except ValueError:
           logging.error('Invalid input')
          

          解析并下載照片

          獲取相冊列表后,逐個請求照片列表信息,進而逐一下載

          def _get_photo(self, album_name, album_id):
           """獲取單個相冊的照片列表信息,并下載該相冊所有照片"""
           photo_list_url = '{}{}'.format(
           'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo?',
           self._get_query_for_request(topicId=album_id))
          
           logging.info('Getting photo list for album {}...'.format(album_name))
           resp = self.session.get(photo_list_url)
           data = self._load_callback_data(resp)
           if data['data']['totalInPage'] == 0:
           return None
          
           file_dir = self.get_path(album_name)
           for item in data['data']['photoList']:
           path = '{}/{}.jpg'.format(file_dir, item['name'])
           logging.info('Downloading {}-{}'.format(album_name, item['name']))
           self._download_image(item['url'], path)
          

          下載圖片也是通過request,記得設置超時時間。

          def _download_image(self, url, path):
           """下載單張照片"""
           try:
           resp = self.session.get(url, timeout=15)
           if resp.status_code == 200:
           open(path, 'wb').write(resp.content)
           except requests.exceptions.Timeout:
           logging.warning('get {} timeout'.format(url))
           except requests.exceptions.ConnectionError as e:
           logging.error(e.__str__)
           finally:
           pass
          

          爬取測試

          • 爬取過程

          capturing

          • 爬取結果

          downloaded photos

          寫在最后

          1. 如果將請求參數中的format由jsonp改成json,則可以直接獲取json數據
          2. 本用例并未使用多進程或多線程,所以速率不算快,還有待優化的地方

          助CSS所提供的animation動畫屬性及2D、3D變換屬性,我們可以擺脫對JavaScript的依賴,設計開發各類效果優秀的前端動態效果,在之前文章和視頻中我們也介紹了不少基于CSS與JavaScript技術實現的各類動畫及頁面元素設計效果。本文主要介紹使用CSS技術實現精美的3D旋轉相冊效果。主要實現效果動畫展示如下:

          純CSS技術實現旋轉相冊效果展示


          核心技術說明

          本例開發主要涉及使用技術包括animation動畫屬性、keyframes關鍵幀、transform變形等相關知識及方法、技術。部分核心技術說明如下:

          1、CSS自定義屬性(變量)

          在使用CSS進行樣式定義時,可以使用自定義屬性,即變量。從變量而言考慮的話,會涉及到變量的定義、賦值與使用等。自定義屬性的聲明使用--表示。其賦值與style樣式其他屬性類似可通過:(冒號)進行賦值。在使用該自定義屬性時需要用var()函數對屬性名進行包裹。如在自定義變量需要進行數學運算時需要使用calc()方法。自定義屬性實例如下:

          :root{--fontSize:2em;}
          p{font-size:var(--fontSize);}

          CSS自定義屬性使用實例如上所示,我們定義了一個fontSize變量,在P元素選擇器中使用了該定義的變量,即設置P段落字體size為2em。

          2、3D變換屬性與方法

          實現3D效果需要使用3D變換相關屬性與方法,其主要屬性方法包括transform-origin(旋轉原點)、transform-style(旋轉類型2D/3D)、perspective(透視點)等屬性,主要方法包括translate位移、scale放縮、rotate旋轉與skew扭曲等。使用實例代碼如下:

          position: absolute;//定位
          transform-origin: center;//中心點
          transform-style: preserve-3d;//類型
          transform: 
          translateZ(400px) rotateY(60deg);
          //沿Z軸移動400px,沿Y軸旋轉60度

          3、flex布局

          本例需要使用flex布局用于實現將頁面元素在頁面中位置進行定位與布局設置,主要設置水平與垂直居中效果,實例代碼如下:

          display: flex;
          justify-content: center;
          align-items: center;

          設計與實現

          在明確以上基本技術點之后,我們就可以收集素材完整3D旋轉相冊的設計與制作。首先第一步就是素材的采集,本例所需圖片如下所示:

          3D旋轉相冊圖片素材

          在完成素材搜集基礎上就可以使用CSS頁面布局技術等,實現頁面的布局,通過旋轉變換,將10張圖片進行不同角度的分布。其中頁面布局代碼如下:

          頁面布局代碼

          完成頁面元素設置之后,就要考慮頁面布局問題,本例需要實現旋轉因此需要將每一個圖片所對應元素進行旋轉等變換設置。部分代碼如下:

          CSS樣式設置

          核心CSS樣式設置如上圖所示,其中我們定義了動畫animate,因此需要使用keyframes對其關鍵幀進行定義,關鍵幀定義如下:

          動畫關鍵幀定義

          通過關鍵幀定義之后,整個gallery層就會繞著y軸進行旋轉最終實現動態旋轉效果。本例靜態展示如下圖所示:

          3D旋轉相冊靜態效果展示

          以上給出了3D旋轉相冊設計及實現過程核心知識點及實現思路過程、核心代碼說明。如需完整代碼請關注并私信。


          本頭條號長期關注編程資訊分享;編程課程、素材、代碼分享及編程培訓。如果您對以上方面有興趣或代碼錯誤、建議與意見,可在評論區回復。更多程序設計相關教程及實例分享,期待大家關注與閱讀!


          主站蜘蛛池模板: 国产免费一区二区三区VR| 亚洲午夜精品第一区二区8050| 国产高清在线精品一区小说| 国产亚洲无线码一区二区| 天天综合色一区二区三区| 亚洲国产精品一区二区成人片国内| 无码少妇一区二区浪潮免费| 自慰无码一区二区三区| 无码日韩人妻AV一区二区三区| 日日摸夜夜添一区| 久久精品午夜一区二区福利| 岛国精品一区免费视频在线观看| 在线免费观看一区二区三区| 无码国产精品一区二区免费虚拟VR | 99久久精品国产免看国产一区 | 天码av无码一区二区三区四区| 亚洲色无码专区一区| 中文字幕一区二区三区久久网站| 久久亚洲中文字幕精品一区四 | 精品视频无码一区二区三区| 亚洲色无码一区二区三区 | 伊人色综合一区二区三区影院视频 | 一区二区三区AV高清免费波多| 欧美一区内射最近更新| 久久精品午夜一区二区福利| 亚洲成在人天堂一区二区| 国产一区二区电影在线观看| 国产一区二区三区免费观在线| 国产成人高清精品一区二区三区| 午夜视频久久久久一区| 无码精品人妻一区二区三区影院| 在线视频国产一区| 波多野结衣一区在线观看| 人成精品视频三区二区一区 | 一区二区三区视频网站| 国产精品一区在线观看你懂的| 真实国产乱子伦精品一区二区三区| 亚洲午夜福利AV一区二区无码 | 一区二区三区无码高清| 日本一区二区高清不卡| 国产综合一区二区在线观看|