首頁 > 軟體

python爬蟲實戰專案之爬取pixiv圖片

2022-07-07 14:02:36

自從接觸python以後就想著爬pixiv,之前因為梯子有點問題就一直擱置,最近換了個梯子就迫不及待試了下。

爬蟲無非request獲取html頁面然後用正規表示式或者beautifulsoup之類現成工具擷取我們想要的頁面,pixiv也不例外。

首先我們來實現模擬登陸,雖然大多數情況不需要我們實現模擬登入,但如果你是會員之類的,登入和不登入網頁就有區別。思路是登入時抓包抓到post請求,看pixiv構建的post的資料表格是什麼格式,我們根據這個格式構建form,然後呼叫post方法去請求,再儲存到session中,之後存取相關頁面用session替代requests即可。

可以看到pixiv登入的網址如下,直接複製:

 抓包找到提交資料的請求:

可以看到表單資料主要是這幾個,經過幾次嘗試,我們在模擬的時候只需要構建password、pixiv_id、post_key再加上一個return_to(第二張)即可。pixiv_id就是我們的賬號,password是密碼,return_to照著填就行,但這個post_key卻是隨機的。

但我們也有辦法,它是我們每次存取登入頁面時動態生成的,這就好辦了,再登入前先爬取一次登入前的頁面,找到postkey。

看到下圖紅圈裡面:

 那就可以直接正則爬取:

def get_postkey():
    login_url='https://accounts.pixiv.net/login?return_to=https%3A%2F%2Fwww.pixiv.net%2F&lang=zh&source=pc&view_type=page'
    response=requests.get(url=login_url,headers=headers,verify=False)
    html=response.text
    # print(html)
    postkey=re.findall('"pixivAccount.postKey":"(.*?)","pixivAccount.recaptchaEnterpriseCheckboxSiteKey"',html)
    return postkey[0]

 然後我們就可以構建封包:

pixiv_id="賬號" # 你的pixiv賬號
password='xxxxx' # 你的pixiv密碼
return_to='https://www.pixiv.net/'
post_key=get_postkey()

範例化一個session物件,然後post提交就能完成模擬登陸: 

session=requests.Session()
 
form_data={
    'pixiv_id':pixiv_id,
    'password':password,
    'return_to':return_to,
    'post_key':post_key
}
login_url1='https://accounts.pixiv.net/login?return_to=https%3A%2F%2Fwww.pixiv.net%2F&lang=zh&source=pc&view_type=page'
res=session.post(url=login_url1,headers=headers,data=form_data)
# 至此模擬登入成功

到此模擬登入就成功了,接下來就是爬我們想要的圖片,以爬排行榜為例:

開啟排行榜頁面,滑鼠懸停圖片,右鍵檢查,可以找到對應的程式碼位置:

找到每張圖片的相似結構,我們可以用BeautifulSoup 找到節點,然後正則爬我們想要的網址:

先找到包含每張圖片各種資訊的節點,通過類名查詢,然後對於每一個節點進行正則提取,提取出對應圖片的下載連結,不過需要特別注意的是,pixiv直接顯示的圖片源是騙你的,真正的圖片連結的形式應該是:

https://i.pximg.net/img-original/img/xxxx/xx/xx/xx/xx/xx/xxxxxxxx_p0.png

這樣的,直接把這個網址複製網頁欄存取會顯示403,因為pixiv限制了必須從pixiv網頁點進這個網址,所以我們首先必須headers構建refer-to,然後通過排行榜提取到資訊後還需要自己手動構建正確的網址:

headers = {'Referer': 'https://www.pixiv.net/',
       
           }
def get_accurate_url(url):
    urll='https://i.pximg.net/img-original/img/' + str(url) + "_p0.jpg"
    return urll

 這裡的程式碼偷了個懶,全部當作jpg來處理,下載的時候再處理png的情況

下載的具體函數,我們對每一個網址的後續部分提取出來作名字,隨機睡眠1到4秒防止pixiv認出我們是爬蟲把我們ip給封了,之後就是對網址進行存取下載,這裡如果存取返回的狀態碼是404說明它其實是個png格式的圖片,所以對png格式的檔案重新構建正確的網址即可:

def download(list,filename):
    i=1
    for url in list:
        pic_name=re.findall("https://i.pximg.net/img-original/img/(.*?)_p0.jpg",str(url))
        pic_name1=str(pic_name[0]).replace("/",".")
        r = random.randint(1, 4)
        time.sleep(r)
        response=requests.get(url=url,headers=headers,verify=False)
        if(response.status_code==404):
            the_url='https://i.pximg.net/img-original/img/' + str(pic_name[0]) + "_p0.png"
            response = requests.get(url=the_url, headers=headers, verify=False)
            with open(path + filename + '/' + str(pic_name1) + '.png', 'wb') as f:
                f.write(response.content)
                print("第" + str(i) + "張圖片已下載成功!!")
        else:
            with open(path + filename + '/' + str(pic_name1) + '.jpg', 'wb') as f:
                f.write(response.content)
                print("第" + str(i) + "張圖片已下載成功!!")
        i+=1

最後就是成功下載排行榜的圖片:

另外我在爬的時候發現pixiv很多網頁獲取時會隱藏body部分的內容,包括但不限於各個tag的網頁和單個id圖片的網頁,一開始以為是沒有登入的原因,但是實現登入後發現依然如此,推測可能是body部分內容是子網頁或者javsscript生成之類的,反正前端有一萬種方法達成這個目的,這個之後再研究怎麼爬。

總結

到此這篇關於python爬蟲實戰專案之爬取pixiv圖片的文章就介紹到這了,更多相關python爬取pixiv圖片內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com