Python学习资料整理

04、实战1:爬取猫眼电影排行

2019-07-27  本文已影响0人  即将拥有八块腹肌的程序猿

目标:提取猫眼电影TOP100的电影名称、时间、评分、图片等信息,提取的站点URL为:http://maoyan.com/board/4,提取的结果以文件形式保存下来。

第一步:抓取首页

import requests

def get_one_page(url):

    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 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()

抓取首页

第二步:解析首页

首先观察爬取下来的结果

<dd>

                        <i class="board-index board-index-1">1</i>

    <a href="/films/1203" title="霸王别姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}">

      <img src="//s3plus.meituan.net/v1/mss_e2821d7f0cfe4ac1bf9202ecf9590e67/cdn-prod/file:5788b470/image/loading_2.e3d934bf.png" alt="" class="poster-default" />

      <img data-src="https://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c" alt="霸王别姬" class="board-img" />

    </a>

    <div class="board-item-main">

      <div class="board-item-content">

              <div class="movie-item-info">

        <p class="name"><a href="/films/1203" title="霸王别姬" data-act="boarditem-click" data-val="{movieId:1203}">霸王别姬</a></p>

        <p class="star">

                主演:张国荣,张丰毅,巩俐

        </p>

<p class="releasetime">上映时间:1993-01-01</p>    </div>

    <div class="movie-item-number score-num">

<p class="score"><i class="integer">9.</i><i class="fraction">5</i></p>       

    </div>

      </div>

    </div>

                </dd>

1、一部电影对应的是一个dd节点,排名是在class为board-index的i节点内,正则表达式:

<dd>.*?board-index.*?>(.*?)</i>

2、获取电影图片,在随后的a节点之内有两个img节点,第二个img节点中data-src属性是图片的链接,正则表达式:

<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)"

3、获取电影名称,后面的p节点里,class为name,正则表达式:

<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>

4、主演、发布时间、评分等都是同样的原理正则表达式;

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

定义解析页面的方法parse_one_page():

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

    )

    iterms = re.findall(pattern, html)

    print(iterms)

正则解析

得到的列表结果:

[('1', 'https://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c', '霸王别姬', '\n 主演:张国荣,张丰毅,巩俐\n ', '上映时间:1993-01-01', '9.', '5'), ('2', 'https://p0.meituan.net/movie/283292171619cdfd5b240c8fd093f1eb255670.jpg@160w_220h_1e_1c', '肖申克的救赎', '\n 主演:蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿\n ', '上映时间:1994-09-10(加拿大)', '9.', '5'), ('3', 'https://p0.meituan.net/movie/289f98ceaa8a0ae737d3dc01cd05ab052213631.jpg@160w_220h_1e_1c', '罗马假日', '\n 主演:格利高里·派克,奥黛丽·赫本,埃迪·艾伯特\n ', '上映时间:1953-09-02(美国)', '9.', '1'), ('4', 'https://p1.meituan.net/movie/6bea9af4524dfbd0b668eaa7e187c3df767253.jpg@160w_220h_1e_1c', '这个杀手不太冷', '\n 主演:让·雷诺,加里·奥德曼,娜塔莉·波特曼\n ', '上映时间:1994-09-14(法国)', '9.', '5'), ('5', 'https://p1.meituan.net/movie/b607fba7513e7f15eab170aac1e1400d878112.jpg@160w_220h_1e_1c', '泰坦尼克号', '\n 主演:莱昂纳多·迪卡普里奥,凯特·温丝莱特,比利·赞恩\n ', '上映时间:1998-04-03', '9.', '5'), ('6', 'https://p0.meituan.net/movie/da64660f82b98cdc1b8a3804e69609e041108.jpg@160w_220h_1e_1c', '唐伯虎点秋香', '\n 主演:周星驰,巩俐,郑佩佩\n ', '上映时间:1993-07-01(中国香港)', '9.', '1'), ('7', 'https://p0.meituan.net/movie/46c29a8b8d8424bdda7715e6fd779c66235684.jpg@160w_220h_1e_1c', '魂断蓝桥', '\n 主演:费雯·丽,罗伯特·泰勒,露塞尔·沃特森\n ', '上映时间:1940-05-17(美国)', '9.', '2'), ('8', 'https://p0.meituan.net/movie/223c3e186db3ab4ea3bb14508c709400427933.jpg@160w_220h_1e_1c', '乱世佳人', '\n 主演:费雯·丽,克拉克·盖博,奥利维娅·德哈维兰\n ', '上映时间:1939-12-15(美国)', '9.', '1'), ('9', 'https://p1.meituan.net/movie/ba1ed511668402605ed369350ab779d6319397.jpg@160w_220h_1e_1c', '天空之城', '\n 主演:寺田农,鹫尾真知子,龟山助清\n ', '上映时间:1992', '9.', '1'), ('10', 'https://p0.meituan.net/movie/b0d986a8bf89278afbb19f6abaef70f31206570.jpg@160w_220h_1e_1c', '辛德勒的名单', '\n 主演:连姆·尼森,拉尔夫·费因斯,本·金斯利\n ', '上映时间:1993-12-15(美国)', '9.', '2')]

运行结果

转换成字典:

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

    )

    iterms = re.findall(pattern, html)

    for item in iterms:

        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()

        }

转换成字典 运行结果

第三步:写入文件

通过JSON库的dumps()方法实现字典的序列化,并制定ensure_ascii参数为False,这样保证输出结果是中文形式而不是Unicode编码

def write_to_file(content):

    with open('MaoyanTop100result.txt', 'a', encoding='utf-8') as f:

        f.write(json.dumps(content, ensure_ascii=False) + '\n')

写入文件 运行结果

第四步:分页爬取

为防止爬取速度过快而无响应,增加延时等待

if __name__ == '__main__':

    for i in range(10):

        main(offset=i * 10)

        time.sleep(1)

分页爬取

主函数调用

def main(offset):

    url = 'http://maoyan.com/board/4' + str(offset)

    html = get_one_page(url)

    for item in parse_one_page(html):

        print(item)

        write_to_file(item)

第五步:全部代码

import requests

import re

from requests.exceptions import RequestException

import json

import time

def get_one_page(url):

    try:

        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 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

    )

    iterms = re.findall(pattern, html)

    for item in iterms:

        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('MaoyanTop100result.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)

    html = str(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)

实际运行过程中只有第一次运行成功,后续会报错,出错原因需要再细找:

运行效果

第二天爬取正常,运行结果见下图:

正常运行结果

改善的代码部分:

def main(offset):

    url = 'http://maoyan.com/board/4?offset=' + str(offset)

    html = str(get_one_page(url))

    # html = get_one_page(url)

    for item in parse_one_page(html):

        print(item)

        write_to_file(item)

上一篇下一篇

猜你喜欢

热点阅读