詳解python爬取今日頭條街拍美圖

之前已經(jīng)爬過(guò)今日頭條街拍的美圖,今天再次完善一下代碼吗铐,并詳解爬取過(guò)程及遇到的坑东亦。廢話(huà)不多說(shuō),抓緊上車(chē)?yán)病?/p>

分析頁(yè)面

分析索引頁(yè)

我們打開(kāi)今日頭條官網(wǎng)唬渗,在在搜索框輸入「街拍」


首頁(yè)內(nèi)容

然后點(diǎn)擊確定典阵,跳轉(zhuǎn)到街拍的詳情頁(yè)。


街拍

這里可以看到上方有四個(gè)框镊逝,分別是 綜合壮啊、視頻、圖集撑蒜、用戶(hù)歹啼。

兩種方式

看到這里玄渗,就有兩種不同的抓取方式。

  • 抓取綜合下方的圖集狸眼,這個(gè)方式雖然可以抓取到圖片藤树,但是抓到的圖片只有四張或一張,也就是看到的顯示在標(biāo)題下方的圖片拓萌。而且獲取的圖片還不是高清的岁钓,還要替換每張圖片的地址格式。
  • 抓取圖集下的圖片微王,這種方式可以抓到所有一個(gè)標(biāo)題下的圖片甜紫,但是一頁(yè)顯示的圖片抓取不到。
    我看網(wǎng)上大多是第一種方式骂远,這次為了練習(xí),我們選取第二種方式腰根。
    我們點(diǎn)擊圖集激才,打開(kāi)開(kāi)發(fā)者工具「按F12」,不斷下拉頁(yè)面额嘿,頁(yè)面地址沒(méi)有變化瘸恼,內(nèi)容不斷加載出來(lái),這一看就是 Ajax 加載的頁(yè)面册养。


    詳情

    這里面也有一些坑

  • 如果你點(diǎn)擊圖集东帅,打開(kāi)開(kāi)發(fā)者工具,刷新一下球拦,你會(huì)發(fā)現(xiàn)靠闭,你的頁(yè)面在綜合這一欄。
  • 你會(huì)發(fā)現(xiàn)你找到的上圖的參數(shù)跟我的不一樣坎炼。
    這里你可以刷新之后點(diǎn)擊圖集愧膀,然后向下拖動(dòng)幾個(gè),讓頁(yè)面多加載一些谣光。
    其中「cur_tab:3」這個(gè)參數(shù)中的數(shù)字對(duì)應(yīng)圖集檩淋,這下你明白了吧。
    到這里就好辦了萄金,我們點(diǎn)擊 Preview



    可以看到 data 下方有 article_url 當(dāng)然還有 image_url 蟀悦,你點(diǎn)擊 image_url 你會(huì)發(fā)現(xiàn)只有四個(gè) url ,復(fù)制鏈接在瀏覽器上打開(kāi)你發(fā)現(xiàn) TMD 還不是大圖氧敢,還是縮略圖日戈,所以我們不用它,我們獲取 article_url 福稳,獲取之后再次請(qǐng)求不就完了嗎涎拉。雖說(shuō)麻煩瑞侮,但是我們思路清晰,頭腦發(fā)熱鼓拧,四肢簡(jiǎn)單半火。哎不對(duì),跑題了季俩。

分析詳情頁(yè)

這里我們來(lái)看看詳情頁(yè)的內(nèi)容

詳情頁(yè)分析

這里我們隨便點(diǎn)開(kāi)一個(gè)組圖的 url 來(lái)分析钮糖,我們可以看到返回的數(shù)據(jù)是一大堆 html ,這里有必要說(shuō)一下,我們?cè)讷@取頁(yè)面內(nèi)容的時(shí)候酌住,一般瀏覽器會(huì)返回給我們的是 response 里的內(nèi)容店归。但是我們大多數(shù)爬取數(shù)據(jù),用 xpath 酪我、BeautifulSoup 獲取數(shù)據(jù)消痛,看的是 Elements 里的內(nèi)容。這里一定要看看 response 里的內(nèi)容和 Element 里的是否相同都哭。
這里的圖片地址還真是不好找秩伞,具體怎么找呢,點(diǎn)開(kāi)圖片的地址欺矫,復(fù)制下鏈接纱新,在HTML里「Ctrl + F」就發(fā)現(xiàn)了。是在紅色框里面的穆趴。

上代碼

分析完了就開(kāi)始上代碼爬取
看看需要引入那些庫(kù)

import requests
import re,json,os
from urllib.parse import urlencode
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
#引入模塊config中所有變量
from config import *
import pymongo
from hashlib import md5
from multiprocessing import Pool

這里引用的庫(kù)有點(diǎn)多脸爱,所有本文的干貨也是滿(mǎn)滿(mǎn)滴。

獲取索引頁(yè)數(shù)據(jù)

def get_page_index(offset,keyword):
    # 獲取頁(yè)面的HTML
    data = {
        'offset': offset,
        'format': 'json',
        'keyword': keyword,
        'autoload': 'true',
        'count': '20',
        'cur_tab': 3,
        'from':'gallery'
    }
    try:
        url = 'https://www.toutiao.com/search_content/?' + urlencode(data)
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print('請(qǐng)求失敗')
        return None

獲取索引頁(yè)的內(nèi)容未妹,這里的「offset」是頁(yè)面的規(guī)律簿废、「keyword」是關(guān)鍵字,我們這篇文章是街拍教寂。通過(guò)構(gòu)造參數(shù)捏鱼,拼接 url 。返回頁(yè)面的 text酪耕。

解析索引頁(yè)

def parse_page_index(html):
    # 獲取所有詳情頁(yè)的url
    data = json.loads(html)  #頁(yè)面是json格式的导梆,裝換成字符串格式
    # data.keys()返回所有鍵名
    if data and 'data' in data.keys():
        for item in data.get('data'):
            yield item.get('article_url')

這個(gè)函數(shù)的主要作用就是提取所有的 article_url 。代碼里面已經(jīng)詳細(xì)的說(shuō)明了內(nèi)容迂烁。

解析詳情頁(yè)的url

def get_page_detial(url):
    #請(qǐng)求詳情頁(yè)的url
    try:
        headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
            '(KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.4882.400 QQBrowser/9.7.13039.400'}
        response = requests.get(url,headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print('請(qǐng)求詳情頁(yè)失敗')
        return None

這里不加 headers 是獲取不到數(shù)據(jù)的看尼。

解析詳情頁(yè)

def parse_page_detial(html):
    #獲取詳情頁(yè)的標(biāo)題和圖片地址url
    soup = BeautifulSoup(html, 'lxml')
    title = soup.select('title')[0].get_text()

    #利用正則提取圖片地址
    pattern = re.compile('.*?gallery: JSON.parse\("(.*?)\"\)', re.S)
    result = re.search(pattern,html)
    if result:
        data = json.loads(result.group(1).replace('\\', ''))
        if data and 'sub_images' in data.keys():
            sub_images = data.get('sub_images')
            #提取圖片
            images = [item.get('url') for item in sub_images]
            #保存圖片到本地
            for image in images:download_image(image)
            return {'title':title,
                    'image':images}

這里面有些東西要說(shuō)一下了。
首先盟步,這里獲取的頁(yè)面內(nèi)容是 json 格式的藏斩,我們看一下這里的內(nèi)容


詳情頁(yè)json

這里獲取用BeautifulSoup 獲取 title 很方便,直接去第一個(gè) title 就好了却盘,關(guān)鍵就在這個(gè)image的提取狰域。


image.png

這里是在紅色框里的媳拴,這里涉及到了正則的用法,代碼里用到了反斜杠兆览,這里是轉(zhuǎn)義匹配屈溉,要不然正則會(huì)匹配不到想要的數(shù)據(jù)。
還有在源代碼中出現(xiàn)了好多反斜杠抬探,不去除掉還是沒(méi)辦法匹配子巾。
這些坑跨過(guò)之后就一帆風(fēng)順了。

保存到MongoDB

'''配置文件'''

#鏈接地址
MONGO_URL = 'localhost'

#數(shù)據(jù)庫(kù)名稱(chēng)
MONGO_DB = 'jiepai'

#表名稱(chēng)
MONGO_TABLE = 'jiepai'

KEY_WORD = '街拍'

這是一些配置文件,注意小压,這里的配置文件是在另一個(gè)python文件中寫(xiě)的线梗,所以說(shuō)開(kāi)頭引入的庫(kù)中有一個(gè)注釋。

#引入模塊config中所有變量
from config import *
import pymongo

#聲明MongoDB對(duì)象
client = pymongo.MongoClient(MONGO_URL)
db = client[MONGO_DB]

def save_to_mongo(result):
    if db[MONGO_TABLE].insert(result):
        print('存儲(chǔ)到MongoDB成功')

這里插入到MongoDB怠益。

保存到本地

def save_image(result):
    file_path = '{0}/{1}{2}'.format(os.getcwd(),md5(result).hexdigest(),'jpg')
    if not os.path.exists(file_path):
        with open(file_path,'wb') as f:
            f.write(result)

這里用了 hashlib 庫(kù)的 md5 這個(gè)方法仪搔,目的是為了防止圖片的重復(fù),這個(gè)方法會(huì)根據(jù)圖片的內(nèi)容生成唯一的字符串蜻牢,用來(lái)去重最好不過(guò)了僻造。
這里說(shuō)保存圖片,沒(méi)有下載圖片孩饼,怎么保存,所以還要先下載圖片竹挡。

def download_image(url):
    try:
        print('正在下載',url)
        r = requests.get(url)
        if r.status_code == 200:
            save_image(r.content)
        return False
    except RequestException:
        print('請(qǐng)求圖片出錯(cuò)')
        return False

細(xì)心的伙伴們已經(jīng)發(fā)現(xiàn)镀娶,我們?cè)诮馕鲈斍轫?yè)的時(shí)候插入的這個(gè)下載圖片的函數(shù)。

開(kāi)啟多線(xiàn)程抓取

def main(offset):
    # 調(diào)用函數(shù)
    html = get_page_index(offset,KEY_WORD)
    for url in parse_page_index(html):
        html = get_page_detial(url)
        if html:
            result = parse_page_detial(html)
            save_to_mongo(result)

if __name__ == '__main__':
    pool = Pool()
    group = [x * 20 for x in range(1,21)]
    pool.map(main,group)
    pool.close()
    main()

這里聲明一個(gè)線(xiàn)程池揪罕,調(diào)用 map 方法開(kāi)啟線(xiàn)程就可以了梯码。

總結(jié)

到這里整個(gè)抓取過(guò)程就結(jié)束了『脝總體下來(lái)代碼量要比平時(shí)抓取的要大轩娶,知識(shí)點(diǎn)也有很多。在這個(gè)過(guò)程中框往,即使找著代碼敲也會(huì)發(fā)現(xiàn)不少的問(wèn)題鳄抒。抓取的過(guò)程就是不斷調(diào)試的過(guò)程。
點(diǎn)個(gè)贊再走唄椰弊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末许溅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子秉版,更是在濱河造成了極大的恐慌贤重,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件清焕,死亡現(xiàn)場(chǎng)離奇詭異并蝗,居然都是意外死亡祭犯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門(mén)滚停,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沃粗,“玉大人,你說(shuō)我怎么就攤上這事铐刘∨忝浚” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵镰吵,是天一觀(guān)的道長(zhǎng)檩禾。 經(jīng)常有香客問(wèn)我,道長(zhǎng)疤祭,這世上最難降的妖魔是什么盼产? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮勺馆,結(jié)果婚禮上戏售,老公的妹妹穿的比我還像新娘。我一直安慰自己草穆,他們只是感情好灌灾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著悲柱,像睡著了一般锋喜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上豌鸡,一...
    開(kāi)封第一講書(shū)人閱讀 49,730評(píng)論 1 289
  • 那天嘿般,我揣著相機(jī)與錄音,去河邊找鬼涯冠。 笑死炉奴,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛇更。 我是一名探鬼主播瞻赶,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼派任!你這毒婦竟也來(lái)了共耍?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吨瞎,失蹤者是張志新(化名)和其女友劉穎痹兜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體颤诀,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡字旭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年对湃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遗淳。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拍柒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出屈暗,到底是詐尸還是另有隱情拆讯,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布养叛,位于F島的核電站种呐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏弃甥。R本人自食惡果不足惜爽室,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淆攻。 院中可真熱鬧阔墩,春花似錦、人聲如沸瓶珊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伞芹。三九已至筐高,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丑瞧,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工蜀肘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绊汹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓扮宠,卻偏偏與公主長(zhǎng)得像西乖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坛增,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • 本文是學(xué)習(xí) 天善學(xué)院 Python3爬蟲(chóng)三大案例實(shí)戰(zhàn)分享 / 分析Ajax抓取今日頭條街拍美圖 后所寫(xiě)获雕,感謝崔慶才...
    4ffde5305e8f閱讀 1,808評(píng)論 0 5
  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱(chēng)項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,969評(píng)論 3 119
  • 加油^0^~圓夢(mèng)~ 不吝嗇教予他人楣颠,同時(shí)成全自己尽纽。 加油,要更加刻苦努力了童漩,不要被別人看扁弄贿。 那些總不想別人得到好...
    如是緣起閱讀 655評(píng)論 0 0
  • 寶媽學(xué)點(diǎn)中醫(yī) 1、睡覺(jué)出汗的原因 頭部出汗——熱盛 上半身出汗——積食 全身出汗——陰虛盜汗 2矫膨、流口水——脾虛 ...
    親子閱讀蛻變閱讀 464評(píng)論 0 0
  • 橋接模式就是把事物和其具體實(shí)現(xiàn)分開(kāi)差凹,使他們可以各自獨(dú)立的變化。橋接的用意是:將抽象化與實(shí)現(xiàn)化解耦侧馅,使得二者可以獨(dú)立...
    曉瘋閱讀 190評(píng)論 0 1