Python《成功破解簡單的 動態載入 的爬蟲》

星海千尋發表於2020-12-20

今天我們來爬取一個漫畫網站
在這裡插入圖片描述

這裡由於漫畫數量過於龐大,於是我就簡單地爬取曾經小時候看過的漫畫吧。
比如下面的五個漫畫:
在這裡插入圖片描述

先來分析分析,拿《火影忍者》舉例:
點選進去後可以看到所有的章節羅列。
在這裡插入圖片描述

嗯,這個沒啥說的了,就是搜尋出所有的< a>元素,找出其章節的標籤,並且得到具體章節的連結,這個簡單。

繼續點選其中某個章節進去後發現,是存在多個頁面的插畫,共同組成一個章節,這個總體來說也不難,因為url很有規律,url是遞增的,直到共X頁面,且每一頁只有一張圖片,我們只需要跳轉到每一頁下載一張圖就行,看著思路可還行。
http://comic.kkkkdm.com/comiclist/3/3/1.htm
http://comic.kkkkdm.com/comiclist/3/3/2.htm
http://comic.kkkkdm.com/comiclist/3/3/3.htm
一直到
http://comic.kkkkdm.com/comiclist/3/3/X.htm
在這裡插入圖片描述

結果,在獲取Img的時候獲取不到,始終是空的,是None值。
原因是這個img的元素是經過javascript指令碼動態新增的,因此我們無法獲得其img元素,但是我們也能看到具體嵌入的javascript指令碼資訊,這裡面是產生img的程式碼,因此我們可以通過解析這個程式碼字串的地址來獲得具體圖片的地址。
在這裡插入圖片描述

可是還是會遇到一個問題就是,這個字串的地址資訊包含一個變數,而且經過資訊列印,發現一共包含多個不同名稱的變數,那麼這個變數值是多少呢?

由於它們是javascript的變數值,因此我們就在本頁面找所有的javascript檔案,從中去找。
終於在本頁中找到了一個js檔案如下:
在這裡插入圖片描述

開啟後能看到
在這裡插入圖片描述

這下全部就清晰了,其實那麼多變數的值都是指向了同一個地址。好了這下問題全部清楚了,
講真的幸虧自己曾經大學時候自學過一些簡單的HTML / CSS / JavaScript的知識,不然的話就無法完成漫畫下載了。

我們來找一個圖片來試試水。
在這裡插入圖片描述

測試程式碼如下:

Import requests

def run11():
    with open("D:/estimages/mn.jpg", "wb") as f :
        f.write(requests.get("https://v2.kukudm.com/kuku6comic6/200910/20091010/glgs/Vol_01/cccc.rar 00003A.jpg").content)
        f.close

if __name__ == "__main__":   #主程式入口
    run11()    #呼叫上面的run方法

在這裡插入圖片描述

效果還行,那麼接下來我們上完整程式碼:

# coding: utf-8
from concurrent.futures import ThreadPoolExecutor
import time
import os
import requests
from bs4 import BeautifulSoup

rootrurl = 'http://comic.kkkkdm.com'
server_url = 'https://v2.kukudm.com/'
save_dir = 'D:/estimages/'

headers = {
    "Referer": rootrurl,
    'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36",
    'Accept-Language': 'en-US,en;q=0.8',
    'Cache-Control': 'max-age=0',
    'Connection': 'keep-alive'
}  ###設定請求的頭部,偽裝成瀏覽器


def saveOneCapCore(dir, img_url):
    img = requests.get(img_url)  # 請求圖片的實際URL
    with open(
            '{}/{}'.format(dir, img.url.split("/")[-1]), 'wb') as jpg:  # 請求圖片並寫進去到本地檔案
        jpg.write(img.content)
        print(img_url)


# 從 script 元素裡面獲得出圖片的連結地址
def parseImgUrl(info):
    tmp = info.split('+')[2]
    return server_url + tmp[tmp.find('"') + 1: tmp.find("'")]


def saveOneCap(dir, href):
    # 找到共有多少頁?
    html = BeautifulSoup(requests.get(href, headers=headers).text.encode('iso-8859-1').decode('gbk'),
                         features="html.parser")
    tbl = html.find_all('table')[1]
    info = tbl.find('td')
    totalPages = int(info.get_text().split('|')[1].strip()[1:-1])

    tmpurl = href[: href.find(href.split('/')[-1])]
    for i in range(1, (totalPages + 1)):
        url = '{}{}.htm'.format(tmpurl, i)
        print(url)
        html = BeautifulSoup(requests.get(url, headers=headers).text.encode('iso-8859-1').decode('gbk'),
                             features="html.parser")

        tbl = html.find_all('table')[1]
        info = tbl.find('td').find('script').string

        # saveOneCapCore(dir, html.find('img', {"id" : "comicpic"}).get('src'))  # 動態生成的,無法直接獲得img的地址
        saveOneCapCore(dir, parseImgUrl(info))   # img的地址是動態生成,因此需要從javascript中解析出來


def saveOnePageFunc(dir, capters):
    for cap in capters:
        # 按照tag和圖片組的內容來建立目錄
        new_dir = '{}{}/{}'.format(save_dir, dir, cap.get_text())
        if not os.path.exists(new_dir):
            os.makedirs(new_dir)

        saveOneCap(new_dir, rootrurl + cap.get('href'))
    pass


def tagSpider(tag, url):
    # 解析當前頁面
    html = BeautifulSoup(requests.get(url, headers=headers).text.encode('iso-8859-1').decode('gbk'),
                         features="html.parser")
    # 提交一個儲存頁面的任務
    saveOnePageFunc(tag, html.find('dl', {'id': 'comiclistn'}).find_all('a')[::4])

    print("thread work over. ")


if __name__ == '__main__':

    # 獲得所有標籤
    taglist = {'火影忍者': 'http://comic.kkkkdm.com/comiclist/3/',
               '犬夜叉': 'http://comic.kkkkdm.com/comiclist/833/',
               '灌籃高手': 'http://comic.kkkkdm.com/comiclist/34/',
               '網球王子': 'http://comic.kkkkdm.com/comiclist/720/',
               '通靈王': 'http://comic.kkkkdm.com/comiclist/163/'}

    # 給每個標籤配備一個執行緒
    with ThreadPoolExecutor(max_workers=10) as t:  # 建立一個最大容納數量為20的執行緒池
        for tag, url in taglist.items():
            t.submit(tagSpider, tag, url)

    # 等待所有執行緒都完成。
    while 1:
        time.sleep(1)

效果如下:
在這裡插入圖片描述

請新增圖片描述
請新增圖片描述
請新增圖片描述
請新增圖片描述

相關文章