人生苦短樟插,我用python--分分鐘下載知乎美圖給你看

上次說了要爬知乎的圖片,于是花了一下午的時間去完成這件事,發(fā)現(xiàn)暫時接觸到的爬蟲總是逃脫不了一個規(guī)律:

  • 模擬登陸
  • 獲取真實網(wǎng)頁HTML源代碼
  • 解析獲取到的網(wǎng)頁源代碼
  • 獲取想要的資源(下載到某個文件夾或者輸出到表格中整合起來)

也許和我說的有一些出入眼耀,應(yīng)該是剛學(xué)這個東西的原因,接下來還想研究一下多線程爬蟲佩憾、添加代理哮伟、爬取海量數(shù)據(jù)并整合成圖標(biāo)形式,先把能做的做了妄帘。

因為是在上一次的基礎(chǔ)上進行的楞黄,所以沒有看上一篇文章的可以先看一下,這里用到的工具跟之前一樣:

  • win7 64位 旗艦版
  • Python 3.5 64-bit
  • PyCharm

這里模擬登陸是跟之前一樣的代碼抡驼,直接貼就是:

logn_url = 'http://www.zhihu.com/#signin'

session = requests.session()

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
}

content = session.get(logn_url, headers=headers).content
soup = BeautifulSoup(content, 'html.parser')


def getxsrf():
    return soup.find('input', attrs={'name': "_xsrf"})['value']
    # 獲取驗證碼
def get_captcha():
    t = str(int(time.time() * 1000))
    captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
    r = session.get(captcha_url, headers=headers)
    with open('captcha.jpg', 'wb') as f:
        f.write(r.content)
        f.close()
    # 用pillow 的 Image 顯示驗證碼
    # 如果沒有安裝 pillow 到源代碼所在的目錄去找到驗證碼然后手動輸入
    try:
        im = Image.open('captcha.jpg')
        im.show()
        im.close()
    except:
        print(u'請到 %s 目錄找到captcha.jpg 手動輸入' % os.path.abspath('captcha.jpg'))
    captcha = input("please input the captcha\n>")
    return captcha


def isLogin():
    # 通過查看用戶個人信息來判斷是否已經(jīng)登錄
    url = "https://www.zhihu.com/settings/profile"
    login_code = session.get(url, allow_redirects=False).status_code
    if int(x=login_code) == 200:
        return True
    else:
        return False


def login(secret, account):
    # 通過輸入的用戶名判斷是否是手機號
    if re.match(r"^1\d{10}$", account):
        print("手機號登錄 \n")
        post_url = 'http://www.zhihu.com/login/phone_num'
        postdata = {
            '_xsrf': getxsrf(),
            'password': secret,
            'remember_me': 'true',
            'phone_num': account,
        }
    else:
        print("郵箱登錄 \n")
        post_url = 'http://www.zhihu.com/login/email'
        postdata = {
            '_xsrf': getxsrf(),
            'password': secret,
            'remember_me': 'true',
            'email': account,
        }
    try:
        # 不需要驗證碼直接登錄成功
        login_page = session.post(post_url, data=postdata, headers=headers)
        login_code = login_page.text
        print(login_page.status)
        print(login_code)
    except:
        # 需要輸入驗證碼后才能登錄成功
        postdata["captcha"] = get_captcha()
        login_page = session.post(post_url, data=postdata, headers=headers)
        login_code = eval(login_page.text)
        print(login_code['msg'])

這里的代碼來自GitHub上的fuck-login項目鬼廓,在此表示感謝,我在原始代碼上進行了改進致盟,原始代碼是適配了Python2.x和Python3.x碎税,但是我學(xué)的是Python3.x所以去掉了一些我沒用過的模塊,也就是說我改進了后的代碼是適用于Python3.x的馏锡。

下面就是準(zhǔn)備獲取圖片了雷蹂,先找一個目標(biāo),最近有一個問題很火:

長得好看眷篇,但沒有男朋友是怎樣的體驗

還記得我列出來的步驟么萎河,模擬登陸之后是獲取真實的網(wǎng)頁源代碼荔泳,什么叫真實的蕉饼,這個問題問得好虐杯,你沒發(fā)現(xiàn)知乎很喜歡用動態(tài)加載技術(shù)么,也就是說昧港,你看到的只是表象擎椰,這里也一樣。

轉(zhuǎn)

問題界面

來创肥,我們先點贊數(shù)最高的妹子上傳的圖片:

Beauty

咳咳咳达舒,好像跑偏了,我們的目標(biāo)是星辰大海叹侄,正確的做法是鼠標(biāo)右鍵查看網(wǎng)頁源代碼:

網(wǎng)頁源代碼

是不是看到了很多圖片鏈接巩搏,當(dāng)然我們要找.jpg、.jpeg趾代、.png后綴的:

[站外圖片上傳中……(8)]

這里有兩個:data-originaldata-actualsrc贯底,實際查看的圖片是data-original的圖片比data-actualsrc的大,下載下來也是如此撒强,但是因為是使用正則去匹配規(guī)則禽捆,而data-original有多項,上面代碼只是貼出來的一部分飘哨,實際匹配的結(jié)果類似這樣:

data-actualsrc

data-actualsrc="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_b.jpg">
data-actualsrc="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_b.jpg">

data-original

data-original="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_r.jpg">
data-original="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_r.jpg" data-actualsrc="https://pic2.zhimg.com/be7600989233bdf438e5ba23f2cdb685_b.jpg">
data-original="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_r.jpg">
data-original="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_r.jpg" data-actualsrc="https://pic2.zhimg.com/b6274542f3785c27ab4a38d4db906efd_b.jpg">
data-original="https://pic2.zhimg.com/0930549116d22ffce22e98c32683d621_r.jpg">

這是在同一段網(wǎng)頁源碼測試下的結(jié)果胚想,匹配后一種會得到多個相同的url地址,解析起來也更麻煩芽隆,這也跟正則寫的簡單有關(guān)系浊服,有興趣的可以到時候自己修改一下正則表達式,這樣下下來的圖片也更高清的多摆马。

分析了正則臼闻,下面要獲取所有的圖片該分析Chrome開發(fā)者面板的Post數(shù)據(jù),因為知乎默認(rèn)只顯示部分回答囤采,我們可以不斷往下拉述呐,直到看到這個:

更多

點擊的時候注意觀察開發(fā)者面板:

enter image description here

簡直完美,傳遞的數(shù)據(jù):

method:next
params:{"url_token":37709992,"pagesize":10,"offset":30}

很眼熟蕉毯,url_token就是問題后面那串?dāng)?shù)字:

https://www.zhihu.com/question/37709992

pagesize是固定的10乓搬,最后一個offset偏移量同樣很好理解,這里顯示10應(yīng)該說的就是默認(rèn)顯示的10個答案代虾,后面還查看到如下數(shù)據(jù):

method:next
params:{"url_token":37709992,"pagesize":10,"offset":20}
method:next
params:{"url_token":37709992,"pagesize":10,"offset":30}

也就是說我們在瀏覽器上每翻過10個答案瀏覽器就會向服務(wù)器發(fā)送Post請求在加載十個答案进肯,恩差不多可以開始寫代碼了。

模擬登陸之后的操作是找到Post的真實地址模擬瀏覽器向服務(wù)器發(fā)送請求:

    url = 'https://www.zhihu.com/node/QuestionAnswerListV2'
    header = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
        'Referer': 'https://www.zhihu.com/question/37709992',
        'Origin': 'https://www.zhihu.com',
        'Accept-Encoding': 'gzip, deflate, br',
    }
    data = {
        'method': 'next',
        'params': '{"url_token":' + str(37709992) + ',"pagesize": "10",' + \
                  '"offset":' + str(offset) + "}",
        '_xsrf': getxsrf(),

    }

注意

發(fā)送Post請求時候請加上'_xsrf': getxsrf()這一行棉磨,否則的話返回的只會是404 Forbidden江掩,應(yīng)該是做了防偽登陸的緣故

然后是寫正則,這里發(fā)現(xiàn)圖片都是被包含在這里面:

<div class="zm-editable-content clearfix">
...
...
</div>

所以先匹配到這一大串內(nèi)容:

        pattern = re.compile('<a class="author-link".*?<span title=.*?<div class="zh-summary.*?' +
                             '<div class="zm-editable-content.*?>(.*?)</div>', re.S)

然后在匹配data-actualsrc里面的圖片鏈接:

pattern = re.compile('data-actualsrc="(.*?)">', re.S)

還有一點要注意的是我們請求之后返回來的是json格式的數(shù)據(jù),所以這里還要用到j(luò)son模塊:

 question = session.post(url, headers=header, data=data)
 dic = json.loads(question.content.decode('ISO-8859-1'))
 li = dic['msg'][0]

然后對其進行解析:

# 這里使用的是第一個正則表達式
items = re.findall(pattern, li)
# 接下來
items = re.findall(pattern, li)
# 存儲圖片鏈接
imagesurl = []
pattern = re.compile('data-actualsrc="(.*?)">', re.S)
for item in items:
    urls = re.findall(pattern, item)
    imagesurl.extend(urls)

執(zhí)行下載操作:

# 存放圖片的地址
PWD = "D:/work/python/zhihu/"
        for url in imagesurl:
            myurl = url
            filename = PWD + str(count) + '.jpg'
            if os.path.isfile(filename):
                print("文件存在:", filename)
                count += 1
                continue
            else:
            # 執(zhí)行下載操作的方法
                downpic(filename, myurl)
                count += 1
                photoNum += 1
            print("一共下載了{(lán)0} 張照片".format(photoNum))
            if not os.path.exists(PWD):
                os.makedirs(PWD)
                # 遞歸調(diào)用
        change(offset, count, photoNum)

# downpic方法源碼
def downpic(filename, url):
    print("正在下載 " + url)
    try:
        r = requests.get(url, stream=True)
        with open(filename, 'wb') as fd:
            for chunk in r.iter_content():
                fd.write(chunk)
    except Exception as e:
        print("下載失敗了", e)

運行結(jié)果

運行結(jié)果
結(jié)果

這只是一部分环形,我之前下了四五百張還在下~當(dāng)然這是后話策泣,感覺現(xiàn)在寫的東西都很簡單,希望下一次能寫出難一點的東西出來抬吟。

這里正則部分參考了這里:

通過Python爬蟲爬取知乎某個問題下的圖片

最后是源碼

源碼中注釋部分只能下載前十個答案里包含的圖片的方法萨咕,還有一些想法未完成,本來是想打印一下正在下載哪個答主的回答火本,然后把圖片分別保存到相應(yīng)的單獨文件夾危队,實現(xiàn)起來有點麻煩就沒去搞,僅供參考钙畔。
親測如果需要下載另一個問題的答案茫陆,只需要在:

 data = {
        'method': 'next',
        'params': '{"url_token":' + str(37709992) + ',"pagesize": "10",' + \
                  '"offset":' + str(offset) + "}",
        '_xsrf': getxsrf(),

    }

更換那串?dāng)?shù)字就行,就好比這樣的形式:

https://www.zhihu.com/question/48720845

但是這種形式的把數(shù)字換上去不起效:

https://www.zhihu.com/question/49078894#answer-41776282

這個好像是知乎熱門問答的鏈接形式擎析,暫時沒有深究
最后盅弛,覺得寫得不錯的可以關(guān)注一下我的公眾號呀~蟹蟹

735909-e84879b3318d959d.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市叔锐,隨后出現(xiàn)的幾起案子挪鹏,更是在濱河造成了極大的恐慌,老刑警劉巖愉烙,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讨盒,死亡現(xiàn)場離奇詭異,居然都是意外死亡步责,警方通過查閱死者的電腦和手機返顺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔓肯,“玉大人遂鹊,你說我怎么就攤上這事≌岚” “怎么了秉扑?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長调限。 經(jīng)常有香客問我舟陆,道長,這世上最難降的妖魔是什么耻矮? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任秦躯,我火速辦了婚禮,結(jié)果婚禮上裆装,老公的妹妹穿的比我還像新娘踱承。我一直安慰自己倡缠,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布茎活。 她就那樣靜靜地躺著毡琉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妙色。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天慧耍,我揣著相機與錄音身辨,去河邊找鬼。 笑死芍碧,一個胖子當(dāng)著我的面吹牛煌珊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泌豆,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼定庵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了踪危?” 一聲冷哼從身側(cè)響起蔬浙,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎贞远,沒想到半個月后畴博,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡蓝仲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年俱病,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袱结。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡亮隙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垢夹,到底是詐尸還是另有隱情溢吻,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布果元,位于F島的核電站煤裙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏噪漾。R本人自食惡果不足惜硼砰,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望欣硼。 院中可真熱鬧题翰,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至血公,卻和暖如春昵仅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背累魔。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工摔笤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人垦写。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓吕世,卻偏偏與公主長得像,于是被迫代替她去往敵國和親梯投。 傳聞我的和親對象是個殘疾皇子命辖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,162評論 25 707
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)分蓖,斷路器尔艇,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,424評論 0 17
  • 秋播 圖文/石豐 【老家記事】昨日和今日關(guān)中老家的天氣么鹤,非常晴朗漓帚,秋高氣爽,清風(fēng)徐來午磁,一掃多日連陰秋雨和濕氣尝抖。 從...
    石豐當(dāng)代藝術(shù)閱讀 573評論 0 0
  • 喜歡吃蛋糕的人很多,享受午后閑暇時光迅皇,冰飲爽后昧辽,蛋糕甜而不膩,讓心情無比美麗登颓。我想搅荞,這是大多數(shù)女孩子無法拒絕的...
    莫倪卡閱讀 324評論 0 0