Python爬虫爬取煎蛋网无聊图

目标

爬取无聊图板块下所有图片和gif

难点

以前煎蛋网是没有难度的,数据都明文写在网页源码里,但是因为爬的人太多,所以做了一些反爬措施,主要是将真实的图片地址用Base64加密了。也希望观看这篇文章的人设计友好爬虫,不要给网站增加太多负担。

做法

一:从网页源码中找到数据位置

我用的是Chrome浏览器,打开网页后按下F12进入开发者工具,在网页中找到你想要的数据,然后通过开发者工具左上角的箭头中的来选中


image.png

二:从网页源码中获取有效信息

获取网页源码可以通过python的requests库或者urllib,甚至你可以用aiohttp来实现异步获取提高性能,这里我用的是requests。

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

通过打印得到的源码可以看到应该出现图片地址的地方变成了
<img src="//img.jandan.net/img/blank.gif" onload="jandan_load_img(this)" /><span class="img-hash">Ly93eDIuc2luYWltZy5jbi9tdzY5MC8wMDcydnZIQ2d5MWZ0MW80NXhwMDBnMzBhOTA1a3UxYS5naWY=</span></p>
这里煎蛋对图片地址做了加密,如果你熟悉Base64的话,看到img-hash你就可以合理的猜测是对地址用了Base64编码。

三:解决网址加密问题

从源码的onload="jandan_load_img(this)"入手,全局查找jandan_load_img函数,发现函数长这样:

image.png

可以发现关键的地方在于var c = jdeSJ67kTPs5IJjmfYHUx7fAWBOhNRGF5V(e, "HWnYZD8ysL1ZI1HaZU7UbZ29tw08jSr0");
继续全局找这个函数:

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这个库可以很方便的对数据进行Base64编码和解码
随意对其中一个地址进行解码,发现长这样
b'//wx2.sinaimg.cn/mw690/0072vvHCgy1ft1o45xp00g30a905ku1a.gif'

# 构建正确的图片地址
url = ('http:' + str(base64.b64decode(item.string.encode('utf-8')))[2:]).replace('\'', '')

四:下载数据到本地

这部分就比较简单了,代码如下

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 是我用来做多进程循环爬取时退出的一个标记
其中BeautifulSoup的使用可以直接查看官网中文文档,除了它之外,还有lxml等,可以根据自己需要了解选取。这些库的作用简单来说就是:

通过html代码构造一个结构化的数据,提供API方便对数据处理

所以,你其实可以完全不用这些解析器,直接通过re编写正则表达式来获取信息也是可以的。

最后

学习爬虫原则:学习技术,友好爬取,不要给服务器增加额外负担。
为什么会给服务器增加负担:

服务器可以比作是一个内存等资源较大的个人计算机,就像你同时开很多进程的时候计算机会卡甚至死机一样,服务器同时处理太多的请求也是这样的道理。

所以如果你只是学习技术而不是看重数据的话,最终可以拿到那最终的一份数据就可以了。
如果需要获取数据的话,可以考虑在夜深人少服务器比较空闲的时候进行。
贴下完整代码

# -*- 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)

如果有碰到什么问题,欢迎留言交流

考虑一下,如果要根据OO跟XX数来抓取的话,要怎么做

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容