貓眼電影的各種爬取方法


按理說這篇隨筆上周就要寫的,可用 request 一直獲取不到詳情頁信息,這天在網上看到一個說法,說是在 requests.get 后加個 headers 就好了,試了試果然可以實現,於是重新回顧一下,正好對 pyquery 的使用方法理解的差不多了,今天用三種方法分別介紹一下貓眼電影的爬取。

一般爬貓眼電影有兩種方法,一種就像我前段時間寫的豆瓣電影爬取方法一樣,可以只獲取全部電影所在的詳情頁內容,然后利用 正則表達式 一個一個提取,另一種就是先獲取全部電影所在的詳情頁內容,在分別獲取每個電影對應的詳情頁內容,再利用 正則表達式pyquery 獲取。

方法一:只獲取全部電影所在的詳情頁內容

import requests
from requests.exceptions import RequestException
from multiprocessing import Pool
import re
import json

def get_one_page(url):           # 獲取網頁的 URL
    try:
        headers = {
            'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
        } # 加上headers,網站認為是瀏覽器訪問,就能爬取貓眼電影
        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>.*?<a.*?title="(.*?)".*?'
                         +'<p.*?releasetime">(.*?)</p>.*?<i.*?integer">(.*?)</i>'
                         +'.*?fraction">(.*?)</i>.*?</dd>',re.S)
    items = re.findall(pattern, html)
    for item in items:
        yield{
            'index':item[0],
            'title':item[1],
            'releasetime':item[2].strip()[5:], # str.strip()就是把這個字符串頭和尾的空格,以及位於頭尾的\n \t之類給刪掉
            'score':item[3]+item[4]
        }

def write_to_file(content):       # 把提取出來的信息寫到文件夾
    with open('result.txt','a',encoding='utf8')as f:
        f.write(json.dumps(content,ensure_ascii=False)+'\n')
        f.close()

def main(offset):
    url = 'http://maoyan.com/board/4?offset=' + str(offset)  # 共提取10個網頁內容
    html = get_one_page(url)     # 每個網頁對應的信息代碼
    for item in parse_one_page(html):
        print(item)
        write_to_file(item)

if __name__ == '__main__':
    pool = Pool()
    pool.map(main,[i*10 for i in range(10)])
    # for i in range(10):
    #     main(i*10)    #for 循環比多進程運行慢,但得到的結果是順序排列的

尤其要講一下

items = re.findall(pattern, html)

for item in items:

yield{

   'index':item[0], 'title':item[1], 'releasetime':item[2].strip()[5:], # str.strip()就是把這個字符串頭和尾的空格,以及位於頭尾的\n \t之類給刪掉 'score':item[3]+item[4]

}

items是一個字典,里面包含了10個 list ,每個item代表一個 list ,包含一部電影的詳細內容, yield 返回的內容必須是 item[0],不能是 items[0]。

 

方法二:先獲取全部電影所在的詳情頁內容,在分別獲取每個電影對應的詳情頁內容

通過觀察發現,html 里 有一個 href="/films/1203",剛好對應第二層詳情頁的 url ,通過正則表達式提取出來,再拼接成字符串,最后經過

get_page_detail(item) 獲取該頁內容,最后再通過 pyquery 進行內容爬取,代碼如下:
import requests
from requests.exceptions import RequestException
from multiprocessing import Pool
from pyquery import PyQuery as pq
import re
import json

def get_page_index(offset):
    try:
        url = 'http://maoyan.com/board/4?offset=' + str(offset)  # 共提取10個網頁內容
        headers = {
            'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
        } # 加上headers,網站認為是瀏覽器訪問,就能爬取貓眼電影
        response = requests.get(url,headers = headers)
        if response.status_code == 200:    # 得到網頁的響應
            return response.text
        return None
    except RequestException:
        return None

def parse_page_index(html):   # 獲取頁面的url
    pattern = re.compile('.*?<dd>.*?<a.*?="(.*?)".*?</a>.*?</dd>',re.S)
    items = re.findall(pattern, html)
    for i in range(10):
        yield(items[i])

def get_page_detail(item):
    try:
        url = 'http://maoyan.com' + str(item)  # 共提取10個網頁內容
        headers = {
            'user-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
        } # 加上headers,網站認為是瀏覽器訪問,就能爬取貓眼電影
        response = requests.get(url,headers = headers)
        if response.status_code == 200:    # 得到網頁的響應
            return response.text
        return None
    except RequestException:
        return None

def parse_page_detail(html):
    doc = pq(html)
    title = doc('.movie-brief-container > h3').text()
    score = doc('.movie-stats-container > div:nth-child(1) > div > span > span').text()
    introduce = doc('.active > div:nth-child(1) > div.mod-content > span').text()
    return{
        'title':title,
        'score':score,
    }

def write_to_file(content):       # 把提取出來的信息寫到文件夾
    with open('result.txt','a',encoding='utf8')as f:
        f.write(json.dumps(content,ensure_ascii=False)+'\n')
        f.close()

def main(offset):
    html = get_page_index(offset)     # 每個網頁對應的信息代碼
    for item in parse_page_index(html):
        html = get_page_detail(item)
        if html:
            result = parse_page_detail(html)
            write_to_file(result)
            print(result)

if __name__ == '__main__':
    # pool = Pool()
    # pool.map(main,[i*10 for i in range(10)])
    for i in range(10):
        main(i*10)    # for循環比多進程運行慢,但得到的結果是順序排列的

得分 score 得到的結果不是,應該是編碼轉換問題,有待進一步解決。

 


免責聲明!

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



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