春節前想看一部美劇,可惜在愛奇藝、騰訊視頻上都沒有資源,然后找呀找,發現了一個網站“80s手機電影網”,在這上面可以找到我想看的那部劇,不過當時還沒放假,就想着白天下載好,周末再一口氣看完
所以就有了一個想法:這次不用迅雷下載,看看能不能爬蟲下來
OK,想到就做
1. 分析網站
網站首頁如下
(1)先搜索一下劇名,點擊搜索后,會新打開一個網頁,顯示搜索結果
從下圖中可以看到初始的請求url以及對應的請求參數
(2)然后再來看看這個頁面的html內容
重點記住這個里面的一個數字:32049,后面會用到
(3)再繼續點擊搜索結果,會跳轉到對應的劇集列表頁,如下
這個頁面有2個重點,
一是url中的后綴數字“32049”,它就是上個頁面讓你記住的數字;
另一個是看下每一集對應的html內容,可以發現每一集都有一個href鏈接,點一下這個href鏈接其實瀏覽器就能自動下載這一集的內容了(這就比較簡單了,直接爬這個url就行,不用做其他處理)
綜上,要爬這部劇,需要如下2個步驟
(1)請求初始的搜索url,提取每部劇對應的數字,如32049
(2)根據32049請求劇集列表url,提取每一集對應的下載鏈接
2. 實際代碼
(1)提取電視劇id
有很多地方都有劇名對應的數字,這里我提取title屬性為劇名的a標簽,然后用正則提取href中的數字
關於如何在python中使用正則表達式,可以參考:在python中使用正則表達式(一)、在python中使用正則表達式(二)、在python中使用正則表達式(三)
1 def get_tv_id(self, tv_name): 2 """獲取所查詢電視劇對應的id""" 3 headers = { 4 "Content-Type": "application/x-www-form-urlencoded" 5 } 6 7 data = { 8 "search_typeid": "1", 9 "skey": tv_name, # 用一個變量來表示要搜索的劇名 10 "Input": "搜索" 11 } 12 13 url = "http://www.y80s.com/movie/search/" # 請求url 14 15 response = self.get_html(url, data, headers, "post") 16 17 html = response 18 # print(html) 19 20 soup = BeautifulSoup(html, "html.parser") 21 name_label = soup.find_all("a", title=tv_name) # 獲取所有title屬性為影視劇名稱的<a>標簽,用一個變量來動態表示劇名 22 # print(soup.prettify()) 23 # print(name_label) 24 # print(name_label[0].get('href')) 25 26 ju_id = re.compile(r'(\d+)', re.S) # 定義一個正則表達式,提取標簽內容中的數字 27 if name_label: 28 href_value = ju_id.search(name_label[0].get('href')) 29 if href_value: 30 tv_id = href_value.group() 31 print("查詢影視劇對應的id為:{}".format(tv_id)) 32 # print(type(tv_id)) # 查看獲取到的tv_id的數據類型,如果是int的話,在后續拼接時需要使用str()轉成字符串 33 return tv_id
(2)提取劇集列表中的下載url
首先用上一步獲取的劇名id拼接請求url,然后提取每一集的下載url即可
1 def get_tv_url(self, tv_name): 2 """獲取電視劇的下載url""" 3 tv_id = self.get_tv_id(tv_name) # 調用get_tv_id()方法,獲取tv_id 4 url = "http://www.y80s.com/ju/" + tv_id # 利用tv_id拼接url 5 6 r = self.get_html(url,method="get") 7 html = r 8 soup = BeautifulSoup(html, "html.parser") 9 a_tv_url = soup.find_all("a", title="本地下載") # 提取title屬性為"本地下載"的a標簽,返回一個包含所有a標簽的列表 10 # print(a_tv_url) 11 tv_url = [] 12 for t in a_tv_url: 13 tv_url.append(t.get('href')) # 用get方法獲取每個a標簽中的href屬性值 14 print(tv_url) 15 return tv_url
整體代碼
1 # coding: utf-8 2 """ 3 author: 我是冰霜 4 describe: 爬蟲80s電影網 5 create_time: 2020/01/18 6 """ 7 8 import re 9 from bs4 import BeautifulSoup 10 from requests.exceptions import RequestException 11 import requests 12 13 class DownloadTV: 14 @staticmethod 15 def get_html(url, data=None, header=None, method=None): 16 """獲取一個url的html格式文本內容""" 17 18 if method == "get": 19 response = requests.get(url, params=data, headers=header) 20 else: 21 response = requests.post(url, data=data, headers=header) 22 try: 23 if response.status_code == 200: 24 response.encoding = response.apparent_encoding 25 # print(response.status_code) 26 # print(response.text) 27 return response.text 28 return None 29 except RequestException: 30 print("請求失敗") 31 return None 32 33 def get_tv_id(self, tv_name): 34 """獲取所查詢電視劇對應的id""" 35 headers = { 36 "Content-Type": "application/x-www-form-urlencoded" 37 } 38 39 data = { 40 "search_typeid": "1", 41 "skey": tv_name, # 用一個變量來表示要搜索的劇名 42 "Input": "搜索" 43 } 44 45 url = "http://www.y80s.com/movie/search/" # 請求url 46 47 response = self.get_html(url, data, headers, "post") 48 49 html = response 50 # print(html) 51 52 soup = BeautifulSoup(html, "html.parser") 53 name_label = soup.find_all("a", title=tv_name) # 獲取所有title屬性為影視劇名稱的<a>標簽,用一個變量來動態表示劇名 54 # print(soup.prettify()) 55 # print(name_label) 56 # print(name_label[0].get('href')) 57 58 ju_id = re.compile(r'(\d+)', re.S) # 定義一個正則表達式,提取標簽內容中的數字 59 if name_label: 60 href_value = ju_id.search(name_label[0].get('href')) 61 if href_value: 62 tv_id = href_value.group() 63 print("查詢影視劇對應的id為:{}".format(tv_id)) 64 # print(type(tv_id)) # 查看獲取到的tv_id的數據類型,如果是int的話,在后續拼接時需要使用str()轉成字符串 65 return tv_id 66 67 def get_tv_url(self, tv_name): 68 """獲取電視劇的下載url""" 69 tv_id = self.get_tv_id(tv_name) # 調用get_tv_id()方法,獲取tv_id 70 url = "http://www.y80s.com/ju/" + tv_id # 利用tv_id拼接url 71 72 r = self.get_html(url,method="get") 73 html = r 74 soup = BeautifulSoup(html, "html.parser") 75 a_tv_url = soup.find_all("a", title="本地下載") # 提取title屬性為"本地下載"的a標簽,返回一個包含所有a標簽的列表 76 # print(a_tv_url) 77 tv_url = [] 78 for t in a_tv_url: 79 tv_url.append(t.get('href')) # 用get方法獲取每個a標簽中的href屬性值 80 print(tv_url) 81 return tv_url 82 83 84 if __name__ == '__main__': 85 test = DownloadTV() 86 test.get_tv_url("血疫第一季")
運行一下