適合Python新手的爬蟲練習:網易LOFTER圖片爬蟲

前言

大學畢業到現在已經快一年了,這一年時間裏,我在家裏待了半年。科班出身的我不太適合做銷售,最後還是決定做一名程序員,雖然大學裏C、java、JavaScript、switf學得不咋的,但是我現在的頭髮挺多的。這半年時間裏,我有每天學Python到凌晨3、4點時候,也有天天熬夜寫Bug的時候。

到現在爲止,我都還沒學到Python爬蟲階段。但我對爬蟲充滿了好奇,想要快速掌握點知識,我就嘗試着一點點百度一點點摸索。今天爲大家分享一下,我這個爬蟲渣渣師是如何寫爬蟲項目的。

注:本文只做技術交流,爬取到的圖片切勿用於商業用途。

1. 網頁分析

對於爬蟲程序來說,首先是要先確定方向。我想要的是網易LOFTER上,攝影師的圖片,不僅是圖片而且還是爲壓縮的原圖。注:網易LOFTER上面的圖片有些是無法手動保存在,因爲作者設置了權限,及時手動保存了也不是原圖,它會有網易LOFTER的水印。

獲取用戶的圖片我們會遇到這些問題:

  1. 如何獲取一位用戶的所有圖片?
    答:網易LOFTER提供了用戶歸檔頁,我們可以輕鬆地進行數據分析
  2. 那我們是從歸檔頁獲取用戶的所有圖片嗎?
    答:不是,歸檔頁只是我們獲取用戶圖片的目錄,我們真正要需要的是用戶發表圖片的詳情頁面
  3. 那我們在歸檔頁分析什麼?
    答:我們需要詳情頁面的url,在這裏能夠獲取到
  4. 如何獲取不同用戶的歸檔頁
    答:不同用戶擁有着不同的三級域名
  5. 爬蟲過程中是否需要各種驗證?
    答:從用戶歸檔頁面採集數據不需要驗證
  6. 如何防止爬蟲遇到的403錯誤?
    答:設置請求延時,或使用代理IP。這裏我們使用了請求延時

1.1 HTML分析

不同用戶擁有不同的三級域名,例如:___.lofter.com/view
在這裏插入圖片描述
用戶圖片太多,打開歸檔頁時,所有圖片不會全部加載出來,網易使用了DWR技術,當我們往下瀏覽網頁時,會自動加載DWR數據,這樣我們就能看到其他圖片了。
在這裏插入圖片描述
小結:DWR包含圖片數據

1.2 DWR分析

分析第一個DWR數據,可以知道剛打開歸檔頁面的數據情況,不難發現,每一個dwr最多顯示50條頁面數據。我取幾條數據展示一下:

//#DWR-INSERT
//#DWR-REPLY
var s0={};var s50={};var s1={};var s51={};var s2={};var s52={};var s3={};var s53={};var s4={};var s54={};var s5={};var s55={};var s6={};var s56={};var s7={};var s57={};var s8={};var s58={};var s9={};var s59={};var s10={};var s60={};var s11={};var s61={};var s12={};var s62={};var s13={};var s63={};var s14={};var s64={};var s15={};var s65={};var s16={};var s66={};var s17={};var s67={};var s18={};var s68={};var s19={};var s69={};var s20={};var s70={};var s21={};var s71={};var s22={};var s72={};var s23={};var s73={};var s24={};var s74={};var s25={};var s75={};var s26={};var s76={};var s27={};var s77={};var s28={};var s78={};var s29={};var s79={};var s30={};var s80={};var s31={};var s81={};var s32={};var s82={};var s33={};var s83={};var s34={};var s84={};var s35={};var s85={};var s36={};var s86={};var s37={};var s87={};var s38={};var s88={};var s39={};var s89={};var s40={};var s90={};var s41={};var s91={};var s42={};var s92={};var s43={};var s93={};var s44={};var s94={};var s45={};var s95={};var s46={};var s96={};var s47={};var s97={};var s48={};var s98={};var s49={};var s99={};s0.blogId=487177737;s0.cctype=1;s0.collectionId=0;s0.dayOfMonth=26;s0.id=7652677484;s0.month=1;s0.noteCount=36;s0.reblog=true;s0.tagCount=9;s0.time=1582713720000;s0.type=2;s0.valid=0;s0.values=s50;s0.year=2020;
s50.imgurl="http://imglf6.nosdn0.126.net/img/Y3RDR3J2WmlKOHRxakNIMjBMVWg1V0lwVnVMQ08zMWI5SCsvcER4WWY4TTRPc0MrS0xvY0NRPT0.jpg?imageView&thumbnail=164y164&enlarge=1&quality=90&type=jpg";s50.permalink="1d09be09_1c822976c";s50.noticeLinkTitle="\u5927\u738B\u4E5D\u5343\u5C81: \u7EA2\u82B1\u7EFF\u53F6\u548C\u7F8E\u4EBA";
s1.blogId=487177737;s1.cctype=1;s1.collectionId=0;s1.dayOfMonth=26;s1.id=7652682322;s1.month=1;s1.noteCount=35;s1.reblog=true;s1.tagCount=7;s1.time=1582709760000;s1.type=2;s1.valid=0;s1.values=s51;s1.year=2020;
s51.imgurl="http://imglf3.nosdn0.126.net/img/Q2xScm9YbUlkREp0c1QxdjkyalJ6ZFl2S3E5aDRYZkhxM2d2aTBaektSaXRQbS9UQUNsM1JBPT0.jpg?imageView&thumbnail=164y164&enlarge=1&quality=90&type=jpg";s51.permalink="1d09be09_1c822aa52";s51.noticeLinkTitle="\u6DF3Mirai: / \u5C4F \u8749 /...";
s2.blogId=487177737;s2.cctype=3;s2.collectionId=0;s2.dayOfMonth=26;s2.id=7652686417;s2.month=1;s2.noteCount=67;s2.reblog=true;s2.tagCount=6;s2.time=1582708163906;s2.type=4;s2.valid=0;s2.values=s52;s2.year=2020;
s52.imgurl="http://imglf5.nosdn0.126.net/img/ZWZ4OTlOUU9kYng4L2RZRmxhTmY0bDMxcVFNWkVmcGtFbllLUjlTSDRuY2NrUWRWU0dhdW9nPT0.jpg?imageView&thumbnail=164y164&enlarge=1&quality=90&type=jpg";s52.permalink="1d09be09_1c822ba51";s52.noticeLinkTitle="\u963F\u73C2\u662F\u53EA\u6444\u5F71\u72EE\u5440: \u4E3A\u5F97\u4F0A\u4EBA\u4E00...";

分析第一條DWR數據:

s50.imgurl="http://imglf6.nosdn0.126.net/img/Y3RDR3J2WmlKOHRxakNIMjBMVWg1V0lwVnVMQ08zMWI5SCsvcER4WWY4TTRPc0MrS0xvY0NRPT0.jpg?imageView&thumbnail=164y164&enlarge=1&quality=90&type=jpg";s50.permalink="1d09be09_1c822976c";s50.noticeLinkTitle="\u5927\u738B\u4E5D\u5343\u5C81: \u7EA2\u82B1\u7EFF\u53F6\u548C\u7F8E\u4EBA";
s1.blogId=487177737;s1.cctype=1;s1.collectionId=0;s1.dayOfMonth=26;s1.id=7652682322;s1.month=1;s1.noteCount=35;s1.reblog=true;s1.tagCount=7;s1.time=1582709760000;s1.type=2;s1.valid=0;s1.values=s51;s1.year=2020;

我們可以得到:

s50.imgurl="http://imglf6.nosdn0.126.net/img/Y3RDR3J2WmlKOHRxakNIMjBMVWg1V0lwVnVMQ08zMWI5SCsvcER4WWY4TTRPc0MrS0xvY0NRPT0.jpg?imageView&thumbnail=164y164&enlarge=1&quality=90&type=jpg"; 
# 壓縮圖片url--->http://imglf6.nosdn0.126.net/img/Y3RDR3J2WmlKOHRxakNIMjBMVWg1V0lwVnVMQ08zMWI5SCsvcER4WWY4TTRPc0MrS0xvY0NRPT0.jpg?imageView&thumbnail=164y164&enlarge=1&quality=90&type=jpg
# 原圖url--->http://imglf6.nosdn0.126.net/img/Y3RDR3J2WmlKOHRxakNIMjBMVWg1V0lwVnVMQ08zMWI5SCsvcER4WWY4TTRPc0MrS0xvY0NRPT0.jpg

s50.permalink="1d09be09_1c822976c"
# 詳情頁面url數據:1d09be09_1c822976c
# 完整的詳情頁url:http://loftermeirenzhi.lofter.com/post/1d09be09_1c822976c

s50.noticeLinkTitle="\u5927\u738B\u4E5D\u5343\u5C81:\u7EA2\u82B1\u7EFF\u53F6\u548C\u7F8E\u4EBA";
# Unicode編碼標題
# 大王九千歲:紅花綠葉和美人

s1.blogId=487177737; # 用戶博客id
s1.time=1582709760000; # Unix時間(用戶發表) 2020-02-26 17:36:00

小結:這一步我們得到了這些有用的數據(s50.permalink、s1.time)

1.3 數據整合

有了第一個DWR的數據,我們就可以獲取到其他DWR數據,以及所有詳情頁的url。爲了獲取到其他DWR數據我們又要進行分析了。

當我們瀏覽用戶歸檔頁時,可以通過鼠標、觸摸板、鍵盤等手動方式獲取到其他的DWR數據,在程序中我們可以這樣獲取。
在這裏插入圖片描述
通過獲取當前的時間來獲取最新(第一個)DWR數據,最後再通過第一個DWR中最後一個時間來獲取其他的DWR,直到無DWR數據爲止。

獲取第一個DWR數據:

import time
import requests

url = 'http://loftermeirenzhi.lofter.com/dwr/call/plaincall/ArchiveBean.getArchivePostByTime.dwr'
    payload = {
                "callCount": "1",
                "scriptSessionId": "${scriptSessionId}187",
                # "httpSessionId": "",
                "c0-scriptName": "ArchiveBean",
                "c0-methodName": "getArchivePostByTime",
                "c0-id": "0",
                "c0-param2": "number:%s" % str(time.time() * 1000)[:13], # 獲取當前時間
                "c0-param0": "boolean:false",
                "c0-param1": "number:487177737",	# 用戶博客id
                "c0-param3": "number:50",
                "c0-param4": "boolean:false",
                "batchId": "1"
                }
    headers = {
                # "Content-Type": "text/plain",
                'Referer': 'https://loftermeirenzhi.lofter.com/view',
                # "Host": "loftermeirenzhi.lofter.com",
                # "Origin": "https://loftermeirenzhi.lofter.com",
                "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36 ",
                }
    dwr = requests.post(url, data=payload, headers=headers).text

小結:我們通過所有的DWR數據可以獲取到所有詳情頁url

2. 採集圖片URL

當我們擁有了詳情頁的url,就可以獲取到詳情頁數據了。爲了避免403錯誤,我們需要設置等待時間來獲取網頁。

import time
time.sleep(0.5)	# 

這裏我們簡單分析一下詳情頁html:
無論是a標籤還是img標籤,這裏都有我們需要的圖片url,那我們就直接盤它吧。
在這裏插入圖片描述

# 這裏使用了兩條xpath來匹配,因爲有些網頁的html代碼有差異
images1 = html.xpath("//a[@class='imgclasstag']")	# <class 'list'>
images2 = html.xpath("//a[@class='img imgclasstag']")	# <class 'list'>

# 獲取原圖url
# 圖片 .jpg、.png、.gif、.jpeg
image_url = re.search(r"(.*net/img/.*\.[jnpegif]{3,4})?",image.attrib['bigimgsrc']).group(1)

有了原圖url就可以下載了。

3. 部分代碼分享

我的爬蟲流程:

  1. 獲取歸檔頁html,獲取其中的用戶id(並把html保存在本地,方便第二次運行)
  2. 通過用戶id,以及當前時間,獲取第一個dwr數據
  3. 通過第一個dwr數據中的最後一個時間獲取其他的dwr數據(這裏我保存了dwr數據,但是意義不大。當用戶更新內容後,dwr數據將被重寫)
  4. 提取dwr數據並匹配所有詳情頁url(並把html保存在本地,方便第二次運行)
  5. 獲取所有詳情頁面html(並把html保存在本地,方便第二次運行)
  6. 獲取所有原圖url(並把url保存在本地,方便第二次運行)
  7. 下載原圖
    def collection_details_page_url_module(self):
        """採集歸檔頁html-DWR-詳情頁URL"""
        for user_info in self.user_info_list:
            self.init_path(user_info)     # 初始化路徑
            self.create_directory(self.g_parent_path)  # 檢查或創建目錄
            self.create_directory(self.parent_path)  # 檢查或創建目錄
            print("\n----開始獲取%s-【歸檔頁】-【DWR】-【詳情頁URL】----" % self.user_info)

            # TODO 獲取id
            if not self.check_file(self.archive_html_path):
                self.write_html()
            # 讀取本地信息
            html = self.read_file(self.archive_html_path)
            html = etree.HTML(html)
            try:
                self.get_id(html)
            except BaseException:
                print("再次獲取html及id")
                self.write_html()
                html = self.read_file(self.archive_html_path)
                html = etree.HTML(html)
                self.get_id(html)
            else:
                pass

            print("\n開始採集dwr...")
            url = self.dwr_headers(self.user_id)
            self.get_new_dwr(url)
            self.get_other_dwr(url)

            # TODO 匹配url
            print("\n獲取詳情頁面url...")
            dwr = self.read_file(self.dwr_path)
            permalinks = re.findall("""permalink="([0-9a-z_]*)";""", dwr)
            # 檢查是否有文件存在
            # 爲了保證獲取到最新數據,每次運行建議刪除本地的詳情頁url數據(htmlURL.json)
            if not self.check_file(self.url_path):
                self.write_permalink_dict(permalinks)
            # 驗證數據完整性
            if not len(json.load(open(self.url_path))) == len(permalinks):
                print("數據不完整...再次採集...")
                self.write_permalink_dict(permalinks)

            print("%s :\n【歸檔頁html】\n【DWR】\n【詳情頁URL】\n全部獲取成功!" % user_info)

總結

注:本文只做技術交流,爬取到的圖片切勿用於商業用途。

這是一個很簡單的爬蟲項目,通過分析,我們只要有用戶的三級域名就可以爬取多個用戶的原圖了。

如果你對這個項目感興趣,歡迎一起交流學習,爲了方便學習我將這個項目放在了GitHub上面,歡迎下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章