Python爬蟲爬取煎蛋網(wǎng)無聊圖

目標(biāo)

爬取無聊圖板塊下所有圖片和gif

難點

以前煎蛋網(wǎng)是沒有難度的,數(shù)據(jù)都明文寫在網(wǎng)頁源碼里直晨,但是因為爬的人太多,所以做了一些反爬措施,主要是將真實的圖片地址用Base64加密了跟束。也希望觀看這篇文章的人設(shè)計友好爬蟲,不要給網(wǎng)站增加太多負擔(dān)丑孩。

做法

一:從網(wǎng)頁源碼中找到數(shù)據(jù)位置

我用的是Chrome瀏覽器冀宴,打開網(wǎng)頁后按下F12進入開發(fā)者工具,在網(wǎng)頁中找到你想要的數(shù)據(jù)温学,然后通過開發(fā)者工具左上角的箭頭中的來選中


image.png

二:從網(wǎng)頁源碼中獲取有效信息

獲取網(wǎng)頁源碼可以通過python的requests庫或者urllib略贮,甚至你可以用aiohttp來實現(xiàn)異步獲取提高性能,這里我用的是requests仗岖。

  url = 'http://jandan.net/pic'
  print(requests.get(url).text)

通過打印得到的源碼可以看到應(yīng)該出現(xiàn)圖片地址的地方變成了
<img src="http://img.jandan.net/img/blank.gif" onload="jandan_load_img(this)" /><span class="img-hash">Ly93eDIuc2luYWltZy5jbi9tdzY5MC8wMDcydnZIQ2d5MWZ0MW80NXhwMDBnMzBhOTA1a3UxYS5naWY=</span></p>
這里煎蛋對圖片地址做了加密逃延,如果你熟悉Base64的話,看到img-hash你就可以合理的猜測是對地址用了Base64編碼轧拄。

三:解決網(wǎng)址加密問題

從源碼的onload="jandan_load_img(this)"入手真友,全局查找jandan_load_img函數(shù),發(fā)現(xiàn)函數(shù)長這樣:

image.png

可以發(fā)現(xiàn)關(guān)鍵的地方在于var c = jdeSJ67kTPs5IJjmfYHUx7fAWBOhNRGF5V(e, "HWnYZD8ysL1ZI1HaZU7UbZ29tw08jSr0");
繼續(xù)全局找這個函數(shù):

var jdeSJ67kTPs5IJjmfYHUx7fAWBOhNRGF5V = function(o, y, g) {
    var d = o;
    var l = "DECODE";
    var y = y ? y : "";
    var g = g ? g : 0;
    var h = 4;
    y = md5(y);
    var x = md5(y.substr(0, 16));
    var v = md5(y.substr(16, 16));
    if (h) {
        if (l == "DECODE") {
            var b = md5(microtime());
            var e = b.length - h;
            var u = b.substr(e, h)
        }
    } else {
        var u = ""
    }
    var t = x + md5(x + u);
    var n;
    if (l == "DECODE") {
        g = g ? g + time() : 0;
        tmpstr = g.toString();
        if (tmpstr.length >= 10) {
            o = tmpstr.substr(0, 10) + md5(o + v).substr(0, 16) + o
        } else {
            var f = 10 - tmpstr.length;
            for (var q = 0; q < f; q++) {
                tmpstr = "0" + tmpstr
            }
            o = tmpstr + md5(o + v).substr(0, 16) + o
        }
        n = o
    }
    var k = new Array(256);
    for (var q = 0; q < 256; q++) {
        k[q] = q
    }
    var r = new Array();
    for (var q = 0; q < 256; q++) {
        r[q] = t.charCodeAt(q % t.length)
    }
    for (var p = q = 0; q < 256; q++) {
        p = (p + k[q] + r[q]) % 256;
        tmp = k[q];
        k[q] = k[p];
        k[p] = tmp
    }
    var m = "";
    n = n.split("");
    for (var w = p = q = 0; q < n.length; q++) {
        w = (w + 1) % 256;
        p = (p + k[w]) % 256;
        tmp = k[w];
        k[w] = k[p];
        k[p] = tmp;
        m += chr(ord(n[q]) ^ (k[(k[w] + k[p]) % 256]))
    }
    if (l == "DECODE") {
        m = base64_encode(m);
        var c = new RegExp("=","g");
        m = m.replace(c, "");
        m = u + m;
        m = base64_decode(d)
    }
    return m
};

代碼的解讀呢紧帕,就是它對加密的圖像地址進行了base64解碼盔然,所以解決思路是直接對源碼中的Base64圖像地址進行解碼桅打。
在python中利用base64這個庫可以很方便的對數(shù)據(jù)進行Base64編碼和解碼
隨意對其中一個地址進行解碼,發(fā)現(xiàn)長這樣
b'//wx2.sinaimg.cn/mw690/0072vvHCgy1ft1o45xp00g30a905ku1a.gif'

# 構(gòu)建正確的圖片地址
url = ('http:' + str(base64.b64decode(item.string.encode('utf-8')))[2:]).replace('\'', '')

四:下載數(shù)據(jù)到本地

這部分就比較簡單了愈案,代碼如下

def download_data(url):
    global num
    dir_path = os.path.abspath('..')
    file_name = url.split('.')[2][-8:-1]
    postfix = url.split('.')[-1].replace('\'', '')
    with open(dir_path + f'\\jan_dan\\wu_liao_tu\\{file_name}.{postfix}', 'wb') as f:
        f.write(requests.get(url, headers=header).content)
    print(f'{num} task done')
    num += 1

Flag 是我用來做多進程循環(huán)爬取時退出的一個標(biāo)記
其中BeautifulSoup的使用可以直接查看官網(wǎng)中文文檔挺尾,除了它之外,還有l(wèi)xml等站绪,可以根據(jù)自己需要了解選取遭铺。這些庫的作用簡單來說就是:

通過html代碼構(gòu)造一個結(jié)構(gòu)化的數(shù)據(jù),提供API方便對數(shù)據(jù)處理

所以恢准,你其實可以完全不用這些解析器魂挂,直接通過re編寫正則表達式來獲取信息也是可以的。

最后

學(xué)習(xí)爬蟲原則:學(xué)習(xí)技術(shù)馁筐,友好爬取涂召,不要給服務(wù)器增加額外負擔(dān)。
為什么會給服務(wù)器增加負擔(dān):

服務(wù)器可以比作是一個內(nèi)存等資源較大的個人計算機敏沉,就像你同時開很多進程的時候計算機會卡甚至死機一樣果正,服務(wù)器同時處理太多的請求也是這樣的道理。

所以如果你只是學(xué)習(xí)技術(shù)而不是看重數(shù)據(jù)的話盟迟,最終可以拿到那最終的一份數(shù)據(jù)就可以了秋泳。
如果需要獲取數(shù)據(jù)的話,可以考慮在夜深人少服務(wù)器比較空閑的時候進行攒菠。
貼下完整代碼

# -*- coding:utf-8 -*-
# author: 禾斗  2018.7
import requests
from bs4 import BeautifulSoup
import base64
import os
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import time, random

start_url = 'http://jandan.net/pic/page-232#comments'
header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
    }
num = 0
Flag = True

def download_data(url):
    global num
    dir_path = os.path.abspath('..')
    file_name = url.split('.')[2][-8:-1]
    postfix = url.split('.')[-1].replace('\'', '')
    with open(dir_path + f'\\jan_dan\\wu_liao_tu\\{file_name}.{postfix}', 'wb') as f:
        f.write(requests.get(url, headers=header).content)
    print(f'{num} task done')
    num += 1


def get_wuliaotu(url):
    global start_url, Flag
    try:
        resp = requests.get(url, headers=header)
        bs = BeautifulSoup(resp.text, 'html.parser')
        next_url = 'http:'+ bs.find('a', class_='previous-comment-page').get('href')
    except Exception as err:
        print(f'Error:{err}')
        Flag = False
        return Flag

    url_ls = set()

    for item in bs.find_all('span', class_='img-hash'):
        url = ('http:' + str(base64.b64decode(item.string.encode('utf-8')))[2:]).replace('\'', '')
        url_ls.add(url)

    pool = ProcessPoolExecutor(max_workers=8)
    pool.map(download_data, url_ls)
    url_ls.clear()
    start_url = next_url
    time.sleep(random.randint(3,6))

if __name__ == '__main__':
    while True:
        get_wuliaotu(start_url)

如果有碰到什么問題迫皱,歡迎留言交流

考慮一下,如果要根據(jù)OO跟XX數(shù)來抓取的話辖众,要怎么做

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舍杜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赵辕,更是在濱河造成了極大的恐慌既绩,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件还惠,死亡現(xiàn)場離奇詭異饲握,居然都是意外死亡,警方通過查閱死者的電腦和手機蚕键,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門救欧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锣光,你說我怎么就攤上這事笆怠。” “怎么了誊爹?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵蹬刷,是天一觀的道長瓢捉。 經(jīng)常有香客問我,道長办成,這世上最難降的妖魔是什么泡态? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮迂卢,結(jié)果婚禮上某弦,老公的妹妹穿的比我還像新娘。我一直安慰自己而克,他們只是感情好靶壮,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著员萍,像睡著了一般腾降。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上充活,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機與錄音蜡娶,去河邊找鬼混卵。 笑死,一個胖子當(dāng)著我的面吹牛窖张,可吹牛的內(nèi)容都是我干的幕随。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼宿接,長吁一口氣:“原來是場噩夢啊……” “哼赘淮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起睦霎,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤筏勒,失蹤者是張志新(化名)和其女友劉穎刚梭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡废赞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了檐盟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梯投。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沟涨,靈堂內(nèi)的尸體忽然破棺而出恤批,到底是詐尸還是另有隱情,我是刑警寧澤裹赴,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布喜庞,位于F島的核電站诀浪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏赋荆。R本人自食惡果不足惜笋妥,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望窄潭。 院中可真熱鬧春宣,春花似錦、人聲如沸嫉你。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幽污。三九已至嚷辅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間距误,已是汗流浹背簸搞。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留准潭,地道東北人趁俊。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像刑然,于是被迫代替她去往敵國和親寺擂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容