Python爬取電影天堂

Dwyane_Coding發表於2018-11-01

本文概要

前言:

本文非常淺顯易懂,可以說是零基礎也可快速掌握。如有疑問,歡迎留言,筆者會第一時間回覆。本文程式碼存於github

一、爬蟲的重要性:

如果把網際網路比喻成一個蜘蛛網,那麼Spider就是在網上爬來爬去的蜘蛛。網路蜘蛛通過網頁的連結地址來尋找網頁,從網站某一個頁面(通常是首頁)開始,讀取網頁的內容,找到在網頁中的其它連結地址,然後通過這些連結地址尋找下一個網頁,一直迴圈下去,直到把整個網站所有的網頁都抓取完為止。

摘取部分網友的回覆: 1、之前在北京買房,誰想房價開始瘋長,鏈家的房價等資料分析只給了一小部分,遠遠不能滿足自己的需求。於是晚上花了幾個小時的時間寫了個爬蟲,爬下了北京所有的小區資訊及北京所有小區的所有歷史成交記錄。

2、我的愛人是某網路公司的銷售,需要收集各種企業資訊然後打電話聯絡。於是乎利用採集指令碼抓一坨一坨的資料給她用,而她的同事天天自己搜資料整理到半夜。

二、實踐:爬取電影天堂電影詳情頁

1、網頁分析及爬取第一頁的詳情頁url

從電影天堂最新電影介面。可以看到其第一頁url為 www.ygdy8.net/html/gndy/d… ,第二頁為www.ygdy8.net/html/gndy/d…,第三第四頁也類似

from lxml import etree
import requests


url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_1.html'

headers = {
    'User_Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}

response = requests.get(url,headers=headers)

# response.text 是系統自己預設判斷。但很遺憾判斷錯誤,導致亂碼出現。我們可以採取另外方式 response.content。自己指定格式解碼
# print(response.text)
# print(response.content.decode('gbk'))
print(response.content.decode(encoding="gbk", errors="ignore"))
複製程式碼

先以第一頁為例,列印資料如下:

image.png

分析電影天堂 html 原始碼,可以得出每個 table 標籤就是一個電影

image.png

通過 xpath 拿到每個電影的詳情url

html = etree.HTML(text)
detail_urls = html.xpath("//table[@class='tbspan']//a/@href")
for detail_url in detail_urls:
    print(detail_url)  #加上域名即為詳情 url
複製程式碼

結果如下:

image.png

2、整理程式碼並爬取前7頁的電影列表url

from lxml import etree
import requests

# 域名
BASE_DOMAIN = 'http://www.ygdy8.net'
# url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_1.html'

HEADERS = {
    'User_Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}

def spider():
    base_url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_{}.html'
    for x in range(1,8):
        url = base_url.format(x)
        print(url) # 求出每一頁電影列表的url eg: http://www.ygdy8.net/html/gndy/dyzz/list_23_1.html

if __name__ == '__main__':
    spider()
複製程式碼

3、爬取每一部電影的詳情頁地址

def get_detail_urls(url):
    response = requests.get(url, headers=HEADERS)

    # response.text 是系統自己預設判斷。但很遺憾判斷錯誤,導致亂碼出現。我們可以採取另外方式 response.content。自己指定格式解碼
    # print(response.text)
    # print(response.content.decode('gbk'))
    # print(response.content.decode(encoding="gbk", errors="ignore"))
    text = response.content.decode(encoding="gbk", errors="ignore")

    # 通過 xpath 拿到每個電影的詳情url
    html = etree.HTML(text)
    detail_urls = html.xpath("//table[@class='tbspan']//a/@href")

    detail_urls = map(lambda url:BASE_DOMAIN+url,detail_urls) #這句意思相當於下面一段程式碼:替換列表中的每一個url
    # def abc(url):
    #     return BASE_DOMAIN+url
    # index = 1
    # for detail_url in detail_urls:
    #     detail_url = abc(detail_url)
    #     detail_urls[index] = detail_url
    #     index+1

    return detail_urls
複製程式碼

4、抓取電影詳情頁的資料

獲取詳情頁title

# 解析詳情頁面
def parse_detail_page(url):
    movie = {}
    response = requests.get(url,headers = HEADERS)
    text = response.content.decode('gbk', errors='ignore')
    html = etree.HTML(text)
    # title = html.xpath("//div[@class='title_all']//font[@color='#07519a']")  # 本行47行,下面已修改

   # 列印出 [<Element font at 0x10cb422c8>, <Element font at 0x10cb42308>]
   #  print(title)

    # 為了顯示,我們需要轉一下編碼
    # for x in title:
    #     print(etree.tostring(x,encoding='utf-8').decode('utf-8'))

     # 我們是為了取得文字,所以修改47行
    title = html.xpath("//div[@class='title_all']//font[@color='#07519a']/text()")[0]
    movie['title'] = title

    zoomE = html.xpath("//div[@id='Zoom']") [0] # 求出共同的頂級容器,方便後面求職
    imgs = zoomE.xpath(".//img/@src") # 求出海報和截圖
    cover = imgs[0]
    if len(imgs) > 1:
        screenshot = imgs[1]
        movie['screenshot'] = screenshot
    # print(cover)
    movie['cover'] = cover

    infos = zoomE.xpath(".//text()")

    for index,info in enumerate(infos):
        if info.startswith('◎年&emsp;&emsp;代'):
            info = info.replace("◎年&emsp;&emsp;代", "").strip() # strip 去掉空格
            movie['year'] = info
        elif info.startswith("◎產&emsp;&emsp;地"):
            info = info.replace("◎產&emsp;&emsp;地", "").strip()
            movie["country"] = info
        elif info.startswith("◎類&emsp;&emsp;別"):
            info = info.replace("◎類&emsp;&emsp;別", "").strip()
            movie["category"] = info
        elif info.startswith("◎豆瓣評分"):
            info = info.replace("◎豆瓣評分", "").strip()
            movie["douban_rating"] = info
        elif info.startswith("◎片&emsp;&emsp;長"):
            info = info.replace("◎片&emsp;&emsp;長","").strip()
            movie["duration"] = info
        elif info.startswith("◎導&emsp;&emsp;演"):
            info = info.replace("◎導&emsp;&emsp;演", "").strip()
            movie["director"] = info
        elif info.startswith("◎主&emsp;&emsp;演"):
            actors = []
            actor = info.replace("◎主&emsp;&emsp;演", "").strip()
            actors.append(actor)
            # 因為主演有很多個,再加上其在電影天堂中元素的特殊性,需要遍歷一遍,在分別求出每一個演員
            for x in range(index+1,len(infos)): # 從演員 infos 開始遍歷,求出每一個演員
                actor = infos[x].strip()
                if actor.startswith("◎"): # 也就是到了標籤 的 ◎ 就退出
                    break
                actors.append(actor)
            movie['actor'] = actors
        elif info.startswith('◎簡&emsp;&emsp;介 '):

            # info = info.replace('◎簡&emsp;&emsp;介 ',"").strip()
            for x in range(index+1,len(infos)):
                if infos[x].startswith("◎獲獎情況"):
                  break
                profile = infos[x].strip()
                movie['profile'] = profile
            # print(movie)
        elif info.startswith('◎獲獎情況 '):
            awards = []
            # info = info.replace("◎獲獎情況 ", "").strip()
            for x in range(index+1,len(infos)):
                if infos[x].startswith("【下載地址】"):
                    break
                award = infos[x].strip()
                awards.append(award)
            movie['awards'] = awards
            # print(awards)

    download_url = html.xpath("//td[@bgcolor='#fdfddf']/a/@href")[0]
    movie['download_url'] = download_url
    return  movie
複製程式碼

上述程式碼爬取了電影的每一個資料。為了讓讀者方便對照格式,筆者已經下載了寫此篇文章時的html—— "movie.html",放於github

最後結果:

前7頁結果




更多精彩內容,請關注本人公眾號 “bigdeveloper”——程式設計師大咖秀

相關文章