Python爬蟲(二)——爬取電影天堂,保存下載地址

首先我們開始要分析一下,下載種子我們需要哪幾步:

  1. 獲取所有電影頁的訪問地址
  2. 獲取電影頁源碼
  3. 提取出下載地址
  4. 將下載地址保存

首先第一步,我們來分析一下電影天堂網站的結構,發現他跟我們的古詩文網還是非常類似的,全站靜網結構,不需要登錄,頁面有全新的地址,這對於初學來講是非常容易上手的;接下來我們以國內電影(https://www.ygdy8.net/html/gndy/china/index.html)爲例,先把所有電影詳情頁的地址獲取到:

我們發現我們需要的地址<a href="***" class="ulink">以鏈接的形式存在,且所有的地址都是這種形式,那麼我們可以用正則表達式直接匹配所有符合這種樣式的文本,最後把地址做一個拼接就好了;

我們發現亂碼了,這是因爲什麼,我們之前在爬取古詩文網的時候是沒有這種問題的,這是因爲網站的文字編碼不一樣,在我們python3裏面默認使用的是utf-8,我們看下古詩文網和電影天堂的編碼格式分別是什麼:


我們發現古詩文網的編碼格式就是“utf-8”,而電影天堂的編碼格式是“gb2312”,編碼格式不一樣,當然會亂碼了,所以我們需要設置一下編碼格式:

這下就正常了,總結一下:如果發現獲取的源碼亂碼了,到網頁源碼中搜索一下“charset”,看一下網頁的編碼是什麼
ok,現在源碼我們已經有了,接下來就是獲取詳情頁的地址了:

import requests
import re    # 導入正則表達式庫

url = 'https://www.ygdy8.net/html/gndy/china/index.html'
result = requests.get(url)
result.encoding = 'gb2312'
html = result.text
reg = '<a href="(.*?)" class="ulink">'    # 匹配的規則
href = re.findall(reg,html)    # 在源碼中匹配所有滿足其規則的文本
print(href)

# 輸出結果:
# ['/html/gndy/dyzz/20191204/59430.html', '/html/gndy/jddy/20191203/59421.html', '/html/gndy/jddy/20191203/59420.html', '/html/gndy/dyzz/20191129/59405.html', '/html/gndy/dyzz/20191127/59402.html', '/html/gndy/dyzz/20191126/59401.html', '/html/gndy/dyzz/20191125/59398.html', '/html/gndy/dyzz/20191124/59394.html', '/html/gndy/jddy/20191118/59382.html', '/html/gndy/dyzz/20191115/59376.html', '/html/gndy/dyzz/20191113/59363.html', '/html/gndy/jddy/20191110/59357.html', '/html/gndy/jddy/20191110/59356.html', '/html/gndy/jddy/20191109/59352.html', '/html/gndy/jddy/20191109/59351.html', '/html/gndy/dyzz/20191107/59345.html', '/html/gndy/dyzz/20191101/59301.html', '/html/gndy/dyzz/20191027/59287.html', '/html/gndy/jddy/20191027/59282.html', '/html/gndy/dyzz/20191026/59279.html', '/html/gndy/dyzz/20191024/59273.html', '/html/gndy/jddy/20191019/59253.html', '/html/gndy/dyzz/20191017/59249.html', '/html/gndy/dyzz/20191016/59241.html', '/html/gndy/jddy/20191015/59236.html']

那麼就有兩個問題出現了:

  1. 爲什麼匹配的規則是<a href="(.*?)" class="ulink">?
    我們回顧一下上面我們需要的地址的那部分字段是怎麼樣的
    我們發現,非常相似,就是中間的網址被替換成了 (.*?)
  2. 其中的 (.*?) 是什麼意思?
    那這個 (.*?) 就是未知字符了,他的準確意思是,任意長度的任意字符,這個是正則部分的內容,可以自行百度,這個基本可以說是萬能用法,可以先把這個掌握,後面再慢慢學習其他的

我們現在已經把詳情頁的地址獲取到了,下一步就是訪問詳情頁,然後把磁力鏈接地址獲取到了:


其實就是一樣的操作,這邊就不贅述了,我們發現上面的代碼幾乎有一半都是重複的,獲取源碼、正則匹配的部分可以直接寫成方法:

我們現在已經把一個頁面所有電影的磁力鏈接獲取到了,接下來我們就需要將這些信息存儲起來,當然不要忘記片名,不然哪個是哪個就傻傻分不清了:

 從上面的代碼我們可以看到,已經將一個頁面的磁力鏈接和片名對應,並且保存了起來,這裏如果對zip()和csv讀寫相關有疑問的話,可以自行百度,也可以查看Python3基礎篇——讀寫csv文件python3基礎篇——列表的高級用法兩篇文章;

接下來我們就需要把所有的頁面都處理了,通過網址我們可以發現就是最後的數字變化,那麼我們只需要將網址進行一個拼接就好了

SOS:驚奇的發現,當我們爬取到24頁之後,後面沒有磁力鏈接地址了,那麼我們只好轉戰下載ftp的地址,同樣也是可以下載的:

import requests
import re
import csv

def get_html(url):    # 獲取頁面源碼
    url = url
    result = requests.get(url)    # 發出訪問請求
    result.encoding = 'gb2312'    # 設置編碼格式,搜索頁面源碼charset
    html = result.text            # 獲取源碼
    return html

title = []    # 存儲標題
data = []     # 存儲下載地址

n = 1        # 頁碼
status = 0   # 重新訪問次數

while n < 123:    # 這裏我們使用while循環,處理訪問出錯的頁面
    try:    # 異常處理很重要,不然可能最後一頁前破功了
        # 直接簡單粗暴,拼接地址
        url = 'https://www.ygdy8.net/html/gndy/china/list_4_{}.html'.format(str(n))
        html = get_html(url)
        print(url)    # 將地址打印出來,可以知道現在搜索到哪一頁了
        reg = '<a href="(.*?)" class="ulink">'    # 匹配詳情頁地址規則
        href = re.findall(reg,html)

        for h in href:    # 遍歷頁面所有電影詳情頁
            info_url = 'https://www.ygdy8.net/' + h
            info_html = get_html(info_url)
            try:
                data_reg = '<a href="(.*?)">ftp://'
                title_reg = '<font color=#07519a>(.*?)</font>'
                title_tmp = re.findall(title_reg, info_html)[0]
                data.append(re.findall(data_reg,info_html)[0])    # 將下載地址添加到列表
                title.append(title_tmp)    # 注意,先地址再標題,不然如果頁面沒有下載地址,標題添加進去就不對應了
            except:
                print('{}獲取失敗'.format(title_tmp))    # 打印那部電影出錯了
        n += 1        # 翻頁
        status = 0    # 重新訪問次數情況
    except:    # 如果頁面訪問出錯
        if status < 4:    # 重新訪問三次
            status += 1   # 次數加1
            print('訪問出錯,重新訪問第{}遍'.format(status))    # 輸出錯誤次數信息
        else:
            n += 1        # 如果重新訪問三次還是訪問不到,那麼直接翻頁
            status = 0

all_data = list(zip(title, data))    # 將標題和地址打包
with open('國內電影.csv', 'w', newline='', encoding='utf-8-sig') as f:    # 寫入文件
    writer = csv.writer(f)
    writer.writerows(all_data)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章