【Python3網絡爬蟲】 抓取貓眼電影排行榜

#抓取貓眼電影排行榜前100

#目標: 提取出貓眼電影TOP100的電影名稱、時間、評分、圖片等信息

#提取站點 :http://maoyan.com/board/4 提取的結果以文件形式保存

#使用知識: 網頁基礎 、網絡基礎 、urllib、requests、正則表達式


1.抓取分析:

1.網站頁面 有效信息:影片名稱 主演 上映時間 上映地區 評分 圖片 一頁10條

2.點擊 第二頁 發現上方的URL http://maoyan.com/board/4?offset=10


由此可見 offset代表偏移值


2.抓取首頁

import requests

def get_one_page(url):
    headers ={
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.170 Safari/537.36',
        }
    response = requests.get(url,headers = headers)
    if response.status_code ==200:
        return response.text
    return None

def main():
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    print(html)
    
main()

3.正則提取

先觀察一個條目的源碼:

1.提取排名信息:

這裏可以寫成的正則表達式:<dd>.*?board-index.*?>(.*)</i> 發現可以一對標記只需要寫一個就可以

2.提取電影圖片

可以看到有兩個圖片鏈接,簡單的測試之後,就可以得到 data-src是電影圖片。

正則表達式可以寫爲:<dd>.*?board-index.*?>(.*)</li>.*?data-src = "(.*?)"

3.提取電影名稱

正則表達式 :<dd>.*?board-index.*?>(.*?)</li>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)<a>

4.提取主演、發佈時間評分等內容 :

<dd>.*board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</li>(.*?)</li>.*?fraction.*?>(.*)</li>.*?<dd>

第四個就是完整的正則表達式了,裏面匹配了七個信息。接下來調用findall方法提取所有內容。

def parse_one_page(html):
    pattern = re.compile('<dd>.*board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>
+(.*)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</li>(.*?)</li>.*?fraction.*?>(.*)</li>.*?<dd>','re.S')
    items = re.findall(pattern,html)
    print(items)
for item in items:
    yield{
    'index':'item[0]',
    'image':'item[1]',
    'title':item[2]strip()
    'actor':item[3]strip()[3:] if len(item[3]) >3 else'',
    'time':item[4]strip()[5:] if len(item[4])>5 else '',
    'score':item[5].strip()+item[6].strip()
    }

這樣就可以成功提取 電影的排名 圖片 標題 演員   時間 評分 等內容 並把它賦值爲一個字典 形成結構化數據

4.寫入文件

這裏直接寫入一個文本文件中。這裏通過JSON庫的dumps()方法實現字典的序列化,並指定ensure_ascii參數爲False,這樣就可以保證輸出結果是中文形式而不是Unicode編碼。

def write_to_file(content):
    with open('result.txt','a',encoding='utf-8') as f:
        print(type(json.dumps(content)))
        f.write(json.dumps(content,ensure_ascii=False)+'\n') 

5.整合代碼

最後,實現main()方法調用前面實現的方法,將單頁的電影結果寫入到文件。相關代碼如下:

def main()
    url = 'http://maoyan.com/board/4'
    html = get_one_page(url)
    for item in parse_one_page(html)
        write_to_file(item) 

6.分頁爬取

因爲需要抓取的是top100的電影,所以還需要遍歷一下,給這個鏈接傳入offset參數,實現其他90部電影的爬取,此時添加如下調用 即可:

if __name__=='__main__':
    for i in range(10):
        main(offset=i*10)

這裏還需要將main()方法修改一下,接收一個offset值作爲偏移量,然後構造URL進行爬取。實現代碼如下:

def main(offset):
    url = 'http://maoyan.com/board/4?offset='+str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item) 


7.完整代碼:

import json
import requests
from requests.exceptions import RequestException
import re
import time


def get_one_page(url):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.162 Safari/537.36'
        }
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        return None


def parse_one_page(html):
    pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a'
                         + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>'
                         + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
    items = re.findall(pattern, html)
    for item in items:
        yield {
            'index': item[0],
            'image': item[1],
            'title': item[2],
            'actor': item[3].strip()[3:],
            'time': item[4].strip()[5:],
            'score': item[5] + item[6]
        }


def write_to_file(content):
    with open('result.txt', 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False) + '\n')


def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)
    html = get_one_page(url)
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)


if __name__ == '__main__':
    for i in range(10):
        main(offset=i * 10)
        time.sleep(1)


這個爬蟲是看着崔老師的書寫的,決定自己重新寫一遍,之後換一個網站爬一下。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章