抓取貓眼電影排行

抓取貓眼電影排行html

1. 抓取分析正則表達式

須要抓取的目標URL爲:http://maoyan.com/board/4,打開以後即可以查看到電影的排行,以下圖:json

(注:若是圖片看不清楚請右鍵點擊圖片經過新的標籤打開)服務器

 

排名第一的是霸王別姬,頁面中顯示的有效信息有影片名稱、主演、上映時間、上映地區、評分以及圖片等信息。將該頁面滾動到最下方,能夠發現還有分頁的列表,觀察點擊下一頁時,URL發生了怎樣的變化並記錄這個變化規律:函數

能夠發現第二頁的URL爲http://maoyan.com/board/4?offset=10,第三頁的URL爲http://maoyan.com/board/4?offset=20,以此類推。源碼分析

 

2. 抓取第一頁測試

定義一個函數用於抓取一個頁面,函數的參數就是url,將咱們要抓取頁面的url傳給函數,返回的結果就是服務器端的響應。url

import requests

def get_one_page(url):
    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

發送請求的函數很快就定義了,剩下的問題就是調用這個函數去發請求了,這裏咱們經過main方法來調用:spa

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


if __name__ == '__main__':
    main()

能夠發現上面拿到的html就是第一頁的源碼了,接下來要作的就是從源碼裏面將咱們須要的信息抽取出來(這裏經過正則表達式實現):code

從源碼分析,一部電影的信息就用一個dd標籤存着。首先,須要提取電影的排名信息,而這個信息正好在calss爲board-index的i節點內,這裏使用非貪婪匹配來提取i節點內的信息,正則表達式爲:'<dd>.*?board-index.*?>(.*?)</i>';

隨後須要提取電影的圖片,能夠看到,後面有a節點,其內部有兩個img標籤,通過測試,第二個img標籤的data-src屬性就是圖片的鏈接,因此這裏提取的就是這個屬性的值:'<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)"' ;

再日後,須要抓取電影的名稱,它在後面的p標籤內,class爲name,因此,能夠用name作一個標誌位,而後進一步提取到其內a節點的標籤體:'<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>' ;

最後提取主演、上映時間、評分等內容:

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

 

經過這樣的一個正則表達式就能夠將咱們須要的數據都提取出來了,而後這裏也是經過一個函數去解析一個網頁:

def parse_one_page(html):
    pattern = re.compile('<dd>.*?board-index.*?>(.*?)</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].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()               
} 

這樣就能夠將咱們須要的數據封裝成一個對象返回,接下來就是數據的存儲了,這裏先使用文本直接存儲:

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):
        write_to_file(item)

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

 

3. 完整代碼

import requests
from requests.exceptions import RequestException
import re
import json
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.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime'
        + '.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</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()
        }

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):
        write_to_file(item)


if __name__ == '__main__':
    for i in range(10):
        main(offset=i*10)
        # 防止反爬蟲機制
        time.sleep(2)
相關文章
相關標籤/搜索