小白學 Python 爬蟲(24):2019 豆瓣電影排行

人生苦短,我用 Pythonhtml

前文傳送門:python

小白學 Python 爬蟲(1):開篇mysql

小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝git

小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門github

小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門sql

小白學 Python 爬蟲(5):前置準備(四)數據庫基礎數據庫

小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝json

小白學 Python 爬蟲(7):HTTP 基礎瀏覽器

小白學 Python 爬蟲(8):網頁基礎框架

小白學 Python 爬蟲(9):爬蟲基礎

小白學 Python 爬蟲(10):Session 和 Cookies

小白學 Python 爬蟲(11):urllib 基礎使用(一)

小白學 Python 爬蟲(12):urllib 基礎使用(二)

小白學 Python 爬蟲(13):urllib 基礎使用(三)

小白學 Python 爬蟲(14):urllib 基礎使用(四)

小白學 Python 爬蟲(15):urllib 基礎使用(五)

小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖

小白學 Python 爬蟲(17):Requests 基礎使用

小白學 Python 爬蟲(18):Requests 進階操做

小白學 Python 爬蟲(19):Xpath 基操

小白學 Python 爬蟲(20):Xpath 進階

小白學 Python 爬蟲(21):解析庫 Beautiful Soup(上)

小白學 Python 爬蟲(22):解析庫 Beautiful Soup(下)

小白學 Python 爬蟲(23):解析庫 pyquery 入門

引言

從本篇的標題各位同窗應該已經猜到了,本篇又到了實戰環節~~~

2019 已經快過完了,按照本文推送的時間預估,到 2020 應該還有十來天的時間,又到了各個公司出各類 2019 榜單的時間,小編這裏呢,就先幫豆瓣搞一個 2019 電影評分排行榜,但願豆瓣官方看到不要打我。

鄭重聲明: 本文僅限用做學習等目的。

分析

仍是先看一下咱們要爬取的頁面:

連接:

https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=time&page_limit=20&page_start=0

思惟敏捷的同窗看着上面這個連接可能就已經發現了什麼,對的,這個連接上已經有分頁信息了。

page_limit 應該是一頁的元素, page_start 應該是這一頁開始的一個序號。

咱們往下翻一下頁面,看看下面有沒有下一頁之類的按鈕,翻幾頁看下地址欄的變化是否和咱們推測的一致。

emmmmmmmmm

小編猜錯了,這裏不是下一頁,是加載更多,不過問題不大,一個意思,先點一下咱們看下地址欄:

https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=time&page_limit=20&page_start=20

和前面一個地址做對比能夠發現,只有最後的 page_start 參數有變化,說明咱們剛纔上面的猜想沒有問題。

加載更多多點幾回,能夠發現,這裏的電影是能夠一直日後排的,能夠加載到 2018 年的數據:

emmmmmmmmm,有點尷尬,這個數據居然手動翻出來了,理論上是應該程序本身判斷的。

這裏的懸浮層上已經顯示了咱們想要的數據,接下來的問題是,咱們如何得到這個懸浮層上的數據,直接從 DOM 節點來取能夠麼?

顯然是不行的,不信能夠本身動手試試,每一個電影的懸浮層其實都是同一個 DOM 節點,只是裏面填充的數據不一樣,顯然這個 DOM 節點中的數據是鼠標挪上去的時候才動態加載出來的。

那麼咱們從哪裏能看到加載數據的來源呢?

若是上一篇實戰有仔細看實操過的同窗應該已經想到了, Chrome 瀏覽器開發者模式中的 Network 標籤。

沒錯,就是這裏,咱們看一下:

首先選擇 Network 標籤,而後在下面的標籤上選擇 XHR 。而後鼠標在不一樣的電影上移動,能夠看到鼠標每次移到一張圖片上,就會有一個請求,咱們看一下這個請求的響應信息:

{"r":0,"subject":{"episodes_count":"","star":"40","blacklisted":"available","title":"我身體裏的那個傢伙 내안의 그놈‎ (2019)","url":"https:\/\/movie.douban.com\/subject\/27088750\/","collection_status":"","rate":"7.2","short_comment":{"content":"男主真的他媽帥 可是我真的接受不了和羅美蘭打k ","author":"SOUL"},"is_tv":false,"subtype":"Movie","directors":["姜孝鎮"],"actors":["鄭振永","樸聖雄","羅美蘭","李垂珉","李俊赫","金光奎","閔智雅","尹敬浩","金賢穆","樸慶惠","趙賢榮","尹頌雅","智燦","金凡振 ","鄭元昌","孫光業","黃仁俊","Dae-han Kim"],"duration":"122分鐘","region":"韓國","playable":false,"id":"27088750","types":["劇情","喜劇"],"release_year":"2019"}}

那麼咱們剩下要關心的就是這個請求的地址了,先看下這個請求的地址:

https://movie.douban.com/j/subject_abstract?subject_id=27088750

這裏看起來好像只有最後一個 subject_id 參數是變化的,其餘的都是定死的,多看幾個請求檢驗下咱們的推測,小編這裏就不檢驗了,省得嫌棄說小編水內容。

還有一個問題,最後這個 subject_id 的數據從哪裏來,好像沒見過的,小編憑藉本身多年豐富的開發經驗,猜想這個數據應該是在頁面的上的。咱們接着看下這個電影的頁面 DOM 結構。

看到了沒,這裏的數據是來源於 DOM 結構上的 data-id 屬性。

PS:更新一件事情,一件異常尷尬的事情,小編偶然發現,點擊加載更多的時候,其實是對應了一個 API 接口,這個接口的訪問地址以下:

https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=time&page_limit=20&page_start=20

這個在 NetWork 中有看到,以下圖:

從圖中能夠看到,這裏直接返回了 JSON 數據,而且這個 JSON 數據返回後,順便還修改了地址欄的數據。

這裏獲得的數據以下:

{
    "subjects":[
        {
            "rate":"6.7",
            "cover_x":1382,
            "title":"在無愛之森吶喊",
            "url":"https://movie.douban.com/subject/30337760/",
            "playable":false,
            "cover":"https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2571542101.jpg",
            "id":"30337760",
            "cover_y":2048,
            "is_new":false
        }
    ]
}

由於總體數據有 20 條,太長了放不下,小編這裏僅保留了一條數據。

編碼

有了上面的分析,其實寫代碼就已經很簡單了,咱們全部須要用到的數據均可以直接從 API 接口中直接獲取到 JSON 的數據。

屢一下思路,首先咱們從

https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=time&page_limit=20&page_start=0

這個連接中直接獲取電影的相關數據,這裏對咱們有用的數據是 id ,獲取到這個 id 後,再從

https://movie.douban.com/j/subject_abstract?subject_id=27088750

這個連接中獲取到電影的詳情數據,用上面獲得的 id 替換這裏的 subject_id

好像沒頁面 DOM 解析啥事兒了,哎,真的是一次失敗的選題,下次不再選豆瓣了。

代碼內容有些簡單,小編直接貼出來吧,數據仍是在 Mysql 中開了一張表作存放:

import requests
import pymysql

# 數據庫鏈接
def connect():
    conn = pymysql.connect(host='localhost',
                           port=3306,
                           user='root',
                           password='password',
                           database='test',
                           charset='utf8mb4')

    # 獲取操做遊標
    cursor = conn.cursor()
    return {"conn": conn, "cursor": cursor}

connection = connect()
conn, cursor = connection['conn'], connection['cursor']

sql_insert = "insert into douban2019(id, title, rate, short_comment, duration, subtype, region, release_year, create_date) values (%(id)s, %(title)s, %(rate)s, %(short_comment)s, %(duration)s, %(subtype)s, %(region)s, %(release_year)s, now())"

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
}

flag = True

def get_movie_list(page_start):
    r = requests.get('https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=time&page_limit=20&page_start=' + str(page_start), headers = headers)
    for item in r.json()['subjects']:
        get_movie_info(item['id'])

def get_movie_info(subject_id):
    r = requests.get('https://movie.douban.com/j/subject_abstract?subject_id=' + str(subject_id), headers=headers)

    subject = r.json()['subject']

    if subject['release_year'] != '2019':
        global flag
        flag = False
        return

    print(subject)

    insert_data = {
        "id": subject['id'],
        "title": subject['title'],
        "rate": subject['rate'],
        "short_comment": subject['short_comment']['content'],
        "duration": subject['duration'],
        "subtype": subject['subtype'],
        "region": subject['region'],
        "release_year": subject['release_year']
    }
    cursor.execute(sql_insert, insert_data)
    conn.commit()
    print(subject['title'], '寫入完成')



def main():
    num = 0
    while(flag):
        get_movie_list(num)
        num += 20

if __name__ == '__main__':
    main()

小結

最後小編作了一下簡單的統計,截止目前, 2019 豆瓣電影共計 312 部,評分超過 8.0 分的共計 37 部,超過 8.5 分的共計 14 部,超過 9.0 分的只有 1 部。

下表爲評分超過 8.0 分的,還有沒看過的小夥伴能夠抓緊時間看一下咯~~

名稱 評分
愛爾蘭人 The Irishman‎ (2019) 9.1
銀河英雄傳說 Die Neue These 星亂 第1章 銀河英雄伝説 Die Neue These 星亂 第1章‎ (2019) 8.9
小丑 Joker‎ (2019) 8.8
婚姻故事 Marriage Story‎ (2019) 8.8
玩具總動員4 Toy Story 4‎ (2019) 8.7
寄生蟲 기생충‎ (2019) 8.7
代號基亞斯:復活的魯路修 コードギアス 復活のルルーシュ‎ (2019) 8.7
82年生的金智英 82년생 김지영‎ (2019) 8.7
克勞斯:聖誕節的祕密 Klaus‎ (2019) 8.6
痛苦與榮耀 Dolor y gloria‎ (2019) 8.6
青春期豬頭少年不作懷夢少女的夢 青春ブタ野郎はゆめみる少女の夢を見ない‎ (2019) 8.6
復仇者聯盟4:終局之戰 Avengers: Endgame‎ (2019) 8.5
哪吒之魔童降世‎ (2019) 8.5
普羅米亞 プロメア‎ (2019) 8.5
少年的你‎ (2019) 8.4
少年泰坦出擊大戰少年泰坦 Teen Titans Go! vs Teen Titans‎ (2019) 8.4
悲慘世界 Les misérables‎ (2019) 8.4
個人一級兄弟 나의 특별한 형제‎ (2019) 8.3
燃燒女子的肖像 Portrait de la jeune fille en feu‎ (2019) 8.3
再見鍾情 Mon inconnue‎ (2019) 8.3
我在雨中等你 The Art of Racing in the Rain‎ (2019) 8.2
羅小黑戰記‎ (2019) 8.2
行騙天下JP:浪漫篇 コンフィデンスマンJP‎ (2019) 8.2
阿鬆 劇場版 劇場版 えいがのおそ鬆さん‎ (2019) 8.2
蠟筆小新:新婚旅行颶風之遺失的野原廣志 映畫クレヨンしんちゃん 新婚旅行ハリケーン ~失われたひろし~‎ (2019) 8.2
馭風男孩 The Boy Who Harnessed the Wind‎ (2019) 8.1
對不起,咱們錯過了你 Sorry We Missed You‎ (2019) 8.1
續命之徒:絕命毒師電影 El Camino: A Breaking Bad Movie‎ (2019) 8.1
我失去了身體 J'ai perdu mon corps‎ (2019) 8.1
最初的夢想 Chhichhore‎ (2019) 8.1
千子2 センコロール コネクト‎ (2019) 8.0
地久天長‎ (2019) 8.0
金髮男子 Un rubio‎ (2019) 8.0
心理測量者SS2:第一衛士 PSYCHO-PASS サイコパス Sinners of the System Case.2「First Guardian」‎ (2019) 8.0
漫長的告別 長いお別れ‎ (2019) 8.0
個人喜馬拉雅‎ (2019) 8.0
小委託人 어린 의뢰인‎ (2019) 8.0

示例代碼

本系列的全部代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便你們取用。

示例代碼-Github

示例代碼-Gitee

原文出處:https://www.cnblogs.com/babycomeon/p/12081996.html

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息