貓眼電影爬取(一):requests+正則,並將數據存儲到mysql數據庫


前面講了如何通過pymysql操作數據庫,這次寫一個爬蟲來提取信息,並將數據存儲到mysql數據庫

1.爬取目標

爬取貓眼電影TOP100榜單
要提取的信息包括:電影排名、電影名稱、上映時間、分數

2.分析網頁HTML源碼

可以看到每部電影信息都被包裹在一對<dd>...</dd>標簽中,所以我們只需提取出一個標簽對中的上述信息即可。使用正則表達式提取

3. 完整過程

這個例子有2個關鍵點:正則編寫和數據處理(寫進mysql數據庫)
(1) 正則表達式的編寫

    pattern = re.compile(r'<dd>.*?<i.*?>(\d+)</i>.*?'  # 匹配電影排名(加個?表示非貪婪匹配,不是匹配0次或1次)
                         r'<p class="name"><a.*?data-val=".*?">(.*?)'  # 匹配電影名稱
                         r'</a>.*?<p.*?class="releasetime">(.*?)</p>'  # 匹配上映時間
                         r'.*?<i.*?"integer">(.*?)</i>'   # 匹配分數的整數位
                         r'.*?<i.*?"fraction">(.*?)</i>.*?</dd>', re.S)  # 匹配分數小數位,re.S表示跨行匹配
    m = pattern.findall(html)
    # print(m)

使用findall()方法來匹配所有符合規則的字符,返回一個列表,下面是其中一頁的匹配結果

(2)完整代碼,注意get_data()函數是如何處理數據,然后通過write_sql()函數是寫入數據庫的

# coding: utf-8
# author: hmk

import requests
import re
import pymysql

def get_html(url, header):
    response = requests.get(url, headers=header)
    if response.status_code == 200:
        return response.text
    else:
        return None

def get_data(html, list_data):
    pattern = re.compile(r'<dd>.*?<i.*?>(\d+)</i>.*?'  # 匹配電影排名
                         r'<p class="name"><a.*?data-val=".*?">(.*?)'  # 匹配電影名稱
                         r'</a>.*?<p.*?class="releasetime">(.*?)</p>'  # 匹配上映時間
                         r'.*?<i.*?"integer">(.*?)</i>'  # 匹配分數的整數位
                         r'.*?<i.*?"fraction">(.*?)</i>.*?</dd>', re.S)  # 匹配分數小數位
    m = pattern.findall(html)
    for i in m:  # 因為匹配到的所有結果會以列表形式返回,每部電影信息以元組形式保存,所以可以迭代處理每組電影信息
        ranking = i[0]  # 提取一組電影信息中的排名
        movie = i[1]  # 提取一組電影信息中的名稱
        release_time = i[2]  # 提取一組電影信息中的上映時間
        score = i[3] + i[4]  # 提取一組電影信息中的分數,這里把分數的整數部分和小數部分拼在一起
        list_data.append([ranking, movie, release_time, score])  # 每提取一組電影信息就放到一個列表中,同時追加到一個大列表里,這樣最后得到的大列表就包含所有電影信息

def write_sql(data):
    conn = pymysql.connect(host='localhost',
                           user='root',
                           password='123456',
                           db='test',
                           charset='utf8')
    cur = conn.cursor()

    for i in data:
        """這里的data參數是指正則匹配並處理后的列表數據(是一個大列表,包含所有電影信息,每個電影信息都存在各自的一個列表中;
        對大列表進行迭代,提取每組電影信息,這樣提取到的每組電影信息都是一個小列表,然后就可以把每組電影信息寫入數據庫了)"""
        movie = i  # 每組電影信息,這里可以看做是准備插入數據庫的每組電影數據
        sql = "insert into maoyan_movie(ranking,movie,release_time,score) values(%s, %s, %s, %s)"  # sql插入語句
        try:
            cur.execute(sql, movie)  # 執行sql語句,movie即是指要插入數據庫的數據
            conn.commit()  # 插入完成后,不要忘記提交操作
            print('導入成功')
        except:
            print('導入失敗')
    cur.close()  # 關閉游標
    conn.close()  # 關閉連接

def main():
    start_url = 'http://maoyan.com/board/4'
    depth = 10  # 爬取深度(翻頁)
    header = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
              "Accept-Encoding": "gzip, deflate, sdch",
              "Accept-Language": "zh-CN,zh;q=0.8",
              "Cache-Control": "max-age=0",
              "Connection": "keep-alive",
              "Host": "maoyan.com",
              "Referer": "http://maoyan.com/board",
              "Upgrade-Insecure-Requests": "1",
              "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36"}

    for i in range(depth):
        url = start_url + '?offset=' + str(10 * i)
        html = get_html(url, header)
        list_data = []
        get_data(html, list_data)
        write_sql(list_data)
        #print(list_data)
        # for i in list_data:
        #     t = i
        #     print(t)

if __name__ == "__main__":
    main()


注意一點,在請求url時,加了headers,這里必須加,估計是網站做了限制,直接爬的話會失敗,可能認出請求鏈接的不是一個人而是一只蟲了
代碼中注釋寫得很詳細,不再過多描述了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM