初級(jí)python爬蟲實(shí)戰(zhàn)一——爬取下廚房首頁(yè)高清圖

1. 預(yù)備工作

在花了兩天半時(shí)間研究學(xué)習(xí)了urllib,requests,bs4,lxml等庫(kù)之后,準(zhǔn)備開始一個(gè)簡(jiǎn)單的實(shí)戰(zhàn)——爬取“下廚房”網(wǎng)站首頁(yè)所有的高清大圖。


下廚房首頁(yè)

首先F12觀察一下這些圖片的真實(shí)地址:


F12觀察任意圖片地址

觀察到img =之后有一個(gè)鏈接地址,直接訪問該地址:

直接訪問觀察地址

顯然這是一個(gè)小圖,不是我要的高清圖。再觀察復(fù)制下來(lái)的鏈接
鏈接分析

不難發(fā)現(xiàn),以@為界,鏈接可以分為前后兩個(gè)部分。猜想前一部分是圖片地址,后一部分則是對(duì)圖片進(jìn)行壓縮的參數(shù)。試著刪除@及其之后的部分,再訪問。果然出現(xiàn)了一張高清大圖。
高清大圖真實(shí)地址

這下子基礎(chǔ)部分基本弄清楚了,預(yù)備動(dòng)作就到這里。

2. 開爬!

終于可以開始寫我的第一只爬蟲了,激動(dòng)~

2.1 獲取頁(yè)面,解析結(jié)構(gòu)

首先,通過requests發(fā)起請(qǐng)求

import requests
from lxml import etree

# 模擬瀏覽器訪問
ua = 'Mozilla/5.0 ' \
     '(Windows NT 10.0; Win64; x64) ' \
     'AppleWebKit/537.36 (KHTML, like Gecko) ' \
     'Chrome/80.0.3987.116 Safari/537.36'
header = {'User-Agent': ua}
r = requests.get("http://www.xiachufang.com/", headers=header)
# r = requests.get("http://httpbin.org/", headers=header)

print(r.text)
et = etree.HTML(r.text)
data = et.xpath('//img/@src')
for i in range(len(data)):
    print(data[i])
print(len(data))

控制窗口的輸出信息為:


控制臺(tái)輸出信息

可見一共輸出了75個(gè)數(shù)據(jù),但是其中包含很大一部分:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEXo6Og4/a9sAAAADUlEQVR42gECAP3/AAAAAgABUyucMAAAAABJRU5ErkJggg

這樣的數(shù)據(jù)。顯然這不是我想要的。打印r.text觀察一下這些數(shù)據(jù)在頁(yè)面中的位置。發(fā)現(xiàn)有

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEXo6Og4/a9sAAAADUlEQVR42gECAP3/AAAAAgABUyucMAAAAABJRU5ErkJggg" 
data-src="http://i1.chuimg.com/b7933e0a29d54c53aab854f3ea65c9f3_750w_750h.jpg@2o_50sh_1pr_1l_60w_60h_1c_1e_90q_1wh" 
alt="夏夏2013" 
width="60" 
height="60">

原來(lái)這些用戶分享的圖片,真實(shí)地址在“data-src”屬性中,而非“src”屬性。
查找所有的data-src

data = et.xpath('//img/@data-src')
for i in range(len(data)):
    # print(data[i])
    pass
print(len(data))

輸出結(jié)果為25,也就是原本鏈接地址為src的被篩選掉了,那么怎么才能保存所有的圖呢?
想到了一個(gè)比較low,但是可行的方案:

  1. 找到img標(biāo)簽中不包含data-src屬性但包含src屬性中的src值
  2. 找到img標(biāo)簽中包含data-src屬性的data-src
  3. 合并前兩步中得到的列表
    在代碼中體現(xiàn)為:
et = etree.HTML(r.text)
# 1. 找到img標(biāo)簽中不包含data-src屬性但包含src屬性中的src值
data1 = et.xpath("http://img[not(@data-src) and @src]/@src")
# 2. 找到img標(biāo)簽中包含data-src屬性的data-src
data2 = et.xpath("http://img/@data-src")
# 3. 合并前兩步中得到的列表
img_list= data1 + data2
for i in range(len(img_list)):
    print(img_list[i])
    # pass

觀察輸出結(jié)果:


不完美的結(jié)果

結(jié)果列表中存在空項(xiàng)。解決辦法當(dāng)然是去除空項(xiàng):

# 刪除空元素
while '' in img_list:
    img_list.remove('')

再觀察輸出結(jié)果:


完美的結(jié)果

完美輸出了69個(gè)圖片鏈接。這一部分完成!

2.2 處理img_list列表

由預(yù)備結(jié)果中的分析可知,下一步要做的是對(duì)列表中每一項(xiàng)進(jìn)行分割,只保留高清大圖部分,刪除后面的參數(shù)。也即,保留鏈接中@符號(hào)之前的部分。使用urllib中的parse對(duì)鏈接進(jìn)行分析。
導(dǎo)入urlparse

from urllib.parse import urlparse
for img in img_list:
    o = urlparse(img)

關(guān)于urlparse的用法,這里用一個(gè)例子說(shuō)明:

 o = urlparse.urlparse("http://www.google.com/search?hl=en&q=urlparse&btnG=Google+Search")

參數(shù)
o.scheme 'http'
o.netloc 'www.google.com'
o.path '/search'
o.params ''
o.query 'hl=en&q=urlparse&btnG=Google+Search'
o.fragment ''

故可以對(duì)列表進(jìn)行下面的處理:

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
處理后的url

完美!

2.3 文件操作

有了真實(shí)的url,下面要做的就是下載圖片并保存到本地了。使用文件操作,首先必須導(dǎo)入python內(nèi)置的os模塊。

import os

初始化文件夾,如果不存在就創(chuàng)建一個(gè):

# 文件操作,初始化xiachufang_image文件夾
image_dir = os.path.join(os.curdir, 'xiachufang_image')
if not os.path.isdir(image_dir):
    os.mkdir(image_dir)

2.4 最后一步

遍歷訪問處理后的url,并且以filename保存。(二進(jìn)制寫入)

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    filepath = os.path.join(image_dir, filename)
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
    resp = requests.get(url)
    with open(filepath, 'wb') as f:
        # 二進(jìn)制以塊寫入
        for chunk in resp.iter_content(1024):
            f.write(chunk)

基本沒有問題,但是少下載了幾個(gè)圖。再優(yōu)化一下:

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    filepath = os.path.join(image_dir, filename)
    if not os.path.isdir(os.path.dirname(filepath)):
        os.mkdir(os.path.dirname(filepath))
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
    resp = requests.get(url)
    with open(filepath, 'wb') as f:
        # 二進(jìn)制以塊寫入
        for chunk in resp.iter_content(1024):
            f.write(chunk)

看看文件夾,已經(jīng)全部保存,欣賞一下美食吧~


總覽

大圖1

大圖2

大圖3
大圖4

大圖5

成就感和食欲均滿滿

3. 完整代碼

貼出完整代碼

import os
from urllib.parse import urlparse
import requests
from lxml import etree

# 模擬瀏覽器訪問
ua = 'Mozilla/5.0 ' \
     '(Windows NT 10.0; Win64; x64) ' \
     'AppleWebKit/537.36 (KHTML, like Gecko) ' \
     'Chrome/80.0.3987.116 Safari/537.36'
header = {'User-Agent': ua}
r = requests.get("http://www.xiachufang.com/", headers=header)

# 開始解析
et = etree.HTML(r.text)
# 1. 找到img標(biāo)簽中不包含data-src屬性但包含src屬性中的src值
data1 = et.xpath("http://img[not(@data-src) and @src]/@src")
# 2. 找到img標(biāo)簽中包含data-src屬性的data-src
data2 = et.xpath("http://img/@data-src")
# 3. 合并前兩步中得到的列表
img_list = data1 + data2
# 刪除空元素
while '' in img_list:
    img_list.remove('')

# 文件操作,初始化xiachufang_image文件夾
image_dir = os.path.join(os.curdir, 'xiachufang_image')
# if not os.path.isdir(image_dir):
#     os.mkdir(image_dir)

for img in img_list:
    o = urlparse(img)
    filename = o.path[1:].split('@')[0]
    filepath = os.path.join(image_dir, filename)
    if not os.path.isdir(os.path.dirname(filepath)):
        os.mkdir(os.path.dirname(filepath))
    url = "%s://%s/%s" % (o.scheme, o.netloc, filename)
    print(url)
    resp = requests.get(url)
    with open(filepath, 'wb') as f:
        # 二進(jìn)制以塊寫入
        for chunk in resp.iter_content(1024):
            f.write(chunk)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 這是MrKevin365天寫作計(jì)劃中第6天的寫作內(nèi)容。 明天就是大年30了,按照中國(guó)人的傳統(tǒng),明天意味著春節(jié)的開始...
    MrKevin閱讀 196評(píng)論 0 0
  • 20190221 星期四 霧轉(zhuǎn)晴 寶爸昨晚夜班,剛開學(xué)大寶表現(xiàn)還算積極,今早起來(lái)洗涮吃完飯等著我去送他...
    Ai哲朵花兒閱讀 266評(píng)論 0 1
  • ——鄧翼徐 最近對(duì)那刻畫風(fēng)情萬(wàn)種女人和四大家室興衰的《紅樓夢(mèng)...
    D_eng閱讀 762評(píng)論 0 3

友情鏈接更多精彩內(nèi)容