Python爬蟲: "追新番"網站資源鏈接爬取

来源:https://www.cnblogs.com/tp1226/archive/2018/02/05/8419564.html
-Advertisement-
Play Games

追新番網站提供最新的日劇和日影下載地址,更新比較快。 個人比較喜歡看日劇,因此想著通過爬取該網站,做一個資源地圖 可以查看網站到底有哪些日劇,並且隨時可以下載。 ...


“追新番”網站

追新番網站提供最新的日劇和日影下載地址,更新比較快。

個人比較喜歡看日劇,因此想著通過爬取該網站,做一個資源地圖

可以查看網站到底有哪些日劇,並且隨時可以下載。

資源地圖

爬取的資源地圖如下:

在linux系統上通過 ls | grep keywords 可以輕鬆找到想要的資源(windows直接搜索就行啦)

爬取腳本開發

1. 確定爬取策略

進入多個日劇,可以查看到每個劇的網址都是如下形式:

可以看出,每個日劇網頁都對應一個編號。

因此我們可以通過遍歷編號來爬取。

2. 獲取日劇的名字

打開其中一個日劇的網頁,查看標題的源代碼如下:

可以看到,標題的標簽ID為"pdtname", 我們只要獲取該標簽的文本即可獲取日劇名字

通過beautifulSoup的介面,獲取該標簽內容(去除了名字中多餘東西)

 1     # try get tv name
 2     tag_name = soup.find(id='pdtname')
 3     if None == tag_name:
 4         print('tv_{:0>4d}: not exist.'.format(num))
 5         return None
 6 
 7     # remove signs not need
 8     name = tag_name.get_text().replace(' ', '') 
 9     try:
10         name = name.replace(re.search('【.*】', name).group(0), '') 
11         name = name.replace(re.search('\(.*\)', name).group(0), '') 
12         name = name.replace('', '') 
13         name = name.replace('', '') 
14         name = name.replace('/', '') 
15     except :
16         pass

 

3. 獲取資源鏈接

在每個日劇頁面中同時也包含了資源鏈接的地址,查看源代碼如下:

可以看到資源鏈接使用了一個表塊,並且表塊的ID為"ajax_tbody"

其中每一集都是表的行元素,每一行又包含了幾列來顯示資源的各個信息

我們通過遍歷表的元素來獲取每一集的資源鏈接

    # try get tv resources list
    tag_resources = soup.find(id='ajax_tbody')
    if None == tag_resources:
        print('tv_{:0>4d}: has no resources.'.format(num))
        return None

    # walk resources
    for res in tag_resources.find_all('tr'):

        # get link tag
        tag_a = res.find('a')
        info = res.find_all('td')
        print('resource: ', tag_a.get_text())

        # get download link
        downlink = get_resources_link(session, tag_a.get('href'))

        # record resouces
        tv.resources.append([tag_a.get_text(), info[2].get_text(), downlink, ''])
        delay(1)

 

4. 獲取下載鏈接

點擊其中一個資源,進入下載鏈接頁面,查看源代碼如下

可以看到電驢的下載鏈接標簽ID為"emule_url",因此我們只需要獲取該標簽的文本就可以了(磁力鏈接類似)

不過首先我們還需要先獲取該下載頁面,整體操作代碼如下

def get_resources_link(session, url):
    ''' get tv resources download link  '''

    global domain
    res_url = domain + url

    # open resources page
    resp = session.get(res_url, timeout = 10)
    resp.raise_for_status()

    soup = page_decode(resp.content, resp.encoding)

    tag_emule = soup.find(id='emule_url')
    return tag_emule.get_text() if tag_emule != None else ''

 

5. 將資源下載鏈接保存到本地

其中,由於爬取所有日劇的下載鏈接比較耗時,前面做了判斷可以只爬取標題,日後根據序號再爬取下載鏈接

def save_tv(tv):
    ''' save tv infomation on disk '''

    filename = os.path.join(os.path.abspath(save_dir), '{:0>4d}_{}.txt'.format(tv.num, tv.name))

    global only_catalog
    if only_catalog == True:
        with open(filename, 'a+') as f:
            pass
    else:
        with open(filename, 'w') as f:
            for info in tv.resources:
                f.write(os.linesep.join(info))
                f.write('========' + os.linesep)

以上,就是整個爬取腳本的開發過程。

 

歡迎關註我的代碼倉庫: https://gitee.com/github-18274965/Python-Spider

以後還會開發其餘網站的爬取腳本。

 

附錄

整體代碼:

  1 #!/usr/bin/python3
  2 # -*- coding:utf-8 -*-
  3 
  4 import os
  5 import sys
  6 import re
  7 import requests
  8 from bs4 import BeautifulSoup
  9 from time import sleep
 10 
 11 # website domain
 12 domain = 'http://www.zhuixinfan.com/'
 13 
 14 # spide infomation save directory
 15 save_dir = './tvinfo/'
 16 
 17 # only tv catalog
 18 only_catalog = False
 19 
 20 class TVInfo:
 21     ''' TV infomation class'''
 22 
 23     def __init__(self, num, name):
 24         self.num = num
 25         self.name = name
 26         self.resources = []
 27 
 28 
 29 def delay(seconds):
 30     ''' sleep for secondes '''
 31 
 32     while seconds > 0:
 33         sleep(1)
 34         seconds = seconds - 1
 35 
 36 def page_decode(content, encoding):
 37     ''' decode page '''
 38 
 39     # lxml may failed, then try html.parser
 40     try:
 41         soup = BeautifulSoup(content, 'lxml', from_encoding=encoding)
 42     except:
 43         soup = BeautifulSoup(content, 'html.parser', from_encoding=encoding)
 44 
 45     return soup
 46 
 47 def open_home_page(session):
 48     ''' open home page first as humain being '''
 49 
 50     global domain
 51     home_url = domain + 'main.php'
 52     
 53     # open home page
 54     resp = session.get(home_url, timeout = 10)
 55     resp.raise_for_status()
 56 
 57     # do nothing
 58 
 59 def get_resources_link(session, url):
 60     ''' get tv resources download link  '''
 61     
 62     global domain
 63     res_url = domain + url
 64 
 65     # open resources page
 66     resp = session.get(res_url, timeout = 10)
 67     resp.raise_for_status()
 68 
 69     soup = page_decode(resp.content, resp.encoding)
 70 
 71     tag_emule = soup.find(id='emule_url')
 72     return tag_emule.get_text() if tag_emule != None else ''
 73 
 74 
 75 def spider_tv(session, num):
 76     ''' fetch tv infomaion '''
 77 
 78     global domain
 79     tv_url = domain + 'viewtvplay-{}.html'.format(num)
 80     
 81     # open tv infomation page
 82     resp = session.get(tv_url, timeout = 10)
 83     resp.raise_for_status()
 84 
 85     soup = page_decode(resp.content, resp.encoding)
 86 
 87     # try get tv name
 88     tag_name = soup.find(id='pdtname')
 89     if None == tag_name:
 90         print('tv_{:0>4d}: not exist.'.format(num))
 91         return None
 92     
 93     # try get tv resources list
 94     tag_resources = soup.find(id='ajax_tbody')
 95     if None == tag_resources:
 96         print('tv_{:0>4d}: has no resources.'.format(num))
 97         return None
 98 
 99     # remove signs not need
100     name = tag_name.get_text().replace(' ', '')
101     try:
102         name = name.replace(re.search('【.*】', name).group(0), '')
103         name = name.replace(re.search('\(.*\)', name).group(0), '')
104         name = name.replace('', '')
105         name = name.replace('', '')
106         name = name.replace('/', '')
107     except :
108         pass
109 
110     print('tv_{:0>4d}: {}'.format(num, name))
111 
112     tv = TVInfo(num, name)
113 
114     global only_catalog
115     if only_catalog == True:
116         return tv
117 
118     # walk resources
119     for res in tag_resources.find_all('tr'):
120 
121         # get link tag
122         tag_a = res.find('a')
123         info = res.find_all('td')
124         print('resource: ', tag_a.get_text())
125 
126         # get download link
127         downlink = get_resources_link(session, tag_a.get('href'))
128 
129         # record resouces
130         tv.resources.append([tag_a.get_text(), info[2].get_text(), downlink, ''])
131         delay(1)
132     
133     return tv
134 
135 
136 def save_tv(tv):
137     ''' save tv infomation on disk '''
138 
139     filename = os.path.join(os.path.abspath(save_dir), '{:0>4d}_{}.txt'.format(tv.num, tv.name)) 
140     
141     global only_catalog
142     if only_catalog == True:
143         with open(filename, 'a+') as f:
144             pass
145     else:
146         with open(filename, 'w') as f:
147             for info in tv.resources: 
148                 f.write(os.linesep.join(info))
149                 f.write('========' + os.linesep)
150 
151 def main():
152     
153     start = 1
154     end = 999
155 
156     if len(sys.argv) > 1:
157         start = int(sys.argv[1])
158     
159     if len(sys.argv) > 2:
160         end = int(sys.argv[2])
161 
162     global only_catalog
163     s = input("Only catalog ?[y/N] ")
164     if s == 'y' or s == 'Y':
165         only_catalog = True
166 
167     # headers: firefox_58 on ubuntu
168     headers = {
169         'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0)' 
170                 + ' Gecko/20100101 Firefox/58.0',
171         'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
172         'Accept-Language': 'zh-CN,en-US;q=0.7,en;q=0.3',
173         'Accept-Encoding': 'gzip, deflate',
174         }
175     
176     # create spider session
177     with requests.Session() as s:
178 
179         try:
180             s.headers.update(headers)
181             open_home_page(s)
182             for num in range(start, end+1):
183                 delay(3)
184                 tv = spider_tv(s, num)
185                 if tv != None:
186                     save_tv(tv)
187 
188         except Exception as err:
189             print(err)
190             exit(-1)
191     
192 if __name__ == '__main__':
193     main()

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • https://www.cnblogs.com/jiese/p/3164940.html 將抽象部份與它的實現部份分離,使它們都可以獨立地變化。 橋接模式號稱設計模式中最難理解的模式之一,關鍵就是這個抽象和實現的分離非常讓人奇怪,大部分人剛看到這個定義的時候都會認為實現就是繼承自抽象,那怎麼可能將他 ...
  • 該系列教程系個人原創,並完整發佈在個人官網 "劉江的博客和教程" 所有轉載本文者,需在頂部顯著位置註明原作者及www.liujiangblog.com官網地址。 Python及Django學習QQ群:453131687 很多時候,我們都不是從‘一窮二白’開始編寫模型的,有時候可以從第三方庫中繼承,有 ...
  • 通過前面三篇的分析,我們深入瞭解了AbstractQueuedSynchronizer的內部結構和一些設計理念,知道了AbstractQueuedSynchronizer內部維護了一個同步狀態和兩個排隊區,這兩個排隊區分別是同步隊列和條件隊列。我們還是拿公共廁所做比喻,同步隊列是主要的排隊區,如果公 ...
  • 一、秒殺業務為什麼難做 IM系統,例如QQ或者微博,每個人都讀自己的數據(好友列表、群列表、個人信息)。 微博系統,每個人讀你關註的人的數據,一個人讀多個人的數據。 秒殺系統,庫存只有一份,所有人會在集中的時間讀和寫這些數據,多個人讀一個數據。 例如小米手機每周二的秒殺,可能手機只有1萬部,但瞬時進 ...
  • 相關內容: 繼承:多繼承、super、__init__、重寫父類變數或函數 多態 繼承: 在Python3中,不寫基類的類預設繼承object 繼承就是子類獲得了父類的全部功能:比如學生和老師都有“姓名,性別,年齡、ID”等學校人員屬性,如果學生和老師都直接繼承學校人員的“姓名,性別,年齡、ID”,... ...
  • 案例目標 簡單介紹 redis pipeline 的機制,結合一段實例說明pipeline 在提升吞吐量方面發生的效用。 案例背景 應用系統在數據推送或事件處理過程中,往往出現數據流經過多個網元; 然而在某些服務中,數據操作對redis 是強依賴的,在最近的一次分析中發現: 一次數據推送會對 red ...
  • 當多個類中出現同一個功能,但是具體的主體功能不同,這時可以進行向上抽取,只抽取功能定義,主體功能由特定類實現。 上面這個類使用abstract關鍵字進行區分 抽象類的特點: 1、抽象方法一定在抽象類中。 2、抽象方法和抽象類都必須被abstract關鍵字修飾。 3、抽象類不可以使用new創建對象,因 ...
  • 所謂的JSP(Java Server Page)就是指在HTML中嵌入大量的Java代碼而已。 JSP註釋 顯示註釋(允許客戶端點擊查看源碼看到) <!-- 註釋內容 -->(HTML註釋) 隱式註釋(客戶端無法看見) // 註釋:單行註釋(Java註釋) /* 註釋 */:多行註釋(Java註釋) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...