python爬取豆瓣电影排行榜前250名

爬取豆瓣电影排行榜

  1. 选择页面
    首先,我们打开豆瓣的电影排行榜的页面。网页链接:双击跳转

python爬取豆瓣电影排行榜前250名_第1张图片 2. 页面分析
接下来,我们要在这个页面提取每一部电影的详情节链接,总页码数,每一部电影的短评。
我们先来提取电影详情页的链接。

# 获取豆瓣top250每个页面下的电影豆瓣链接列表
        movies_link_list = html.xpath('//li//div[@class="info"]/div[@class="hd"]/a/@href')

提取导航页的每一部电影的短评。

`# 获取每个页面下的电影的代表影评
        movies_quote_list = html.xpath('//p[@class="quote"]/span[@class="inq"]/text()')`

提取电影排行榜的总页数

`total_page_num = int(html.xpath('string(//span[@class="next"]/preceding-sibling::a[1])'))`

下面,我们提取每一部电影的详细信息。

python爬取豆瓣电影排行榜前250名_第2张图片 我们提取的信息包括上图中的电影排名、名称、链接、评分、评价人数以及各个星级的评价人数,还有电影的导演,编剧、主演、类型、制片国家/地区、语言、上映日期、片长、又名和IMDb链接。代码如下:

				# 获取电影排名
                movie_rank = r'电影排名:{}'.format(html.xpath('string(//div[@class="top250"]/span[@class="top250-no"])'))
                # 获取电影名称
                movie_name = r'电影名称:{}'.format(html.xpath('string(//span[@property="v:itemreviewed"])'))
                # 获取电影链接
                movie_link = r'电影链接:{}'.format(movie_link)
                # 获取电影评分
                movie_score = r'电影评分:{}'.format(html.xpath('string(//strong[@property="v:average"])'))
                # 获取电影评价总人数
                movie_evaluated_people = r'电影评价人数:{}'.format(html.xpath('string(//a[@class="rating_people"])'))
                # 获取电影5个评价星级
                movie_stars_list = [i.strip() for i in
                                    html.xpath('//div[@class="item"]//span[starts-with(@class, "stars")]/text()')]
                # 获取电影5个评价星级对应的评价人数的百分比
                movie_evaluated_per_list = html.xpath('//div[@class="item"]//span[@class="rating_per"]/text()')
  1. 下载页面
try:
        response = requests.get(url, headers)
        if response.status_code == 200:
            return response.content.decode('utf-8')
    except requests.ConnectionError:
        print('网页数据爬取错误!!!!')
        return None

4.保存页面
我把爬取的电影的详细保存到JSON文件。

with open(file_name, 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, indent=4, ensure_ascii=False))
        f.write('\n' * 2)

5.完整代码
下面是完整的代码。

import json
import re
import time

import requests
from lxml import etree


def get_page_source(url, headers):
    """
    获取网页源代码
    :param url: 网页地址
    :param headers: 请求头
    :return: html字符串
    """
    try:
        response = requests.get(url, headers)
        if response.status_code == 200:
            return response.content.decode('utf-8')
    except requests.ConnectionError:
        print('网页数据爬取错误!!!!')
        return None


def get_page_num(page_source):
    """
    获取页面总页数
    :param page_source: html字符串
    :return: 页数(int)
    """
    html = etree.HTML(page_source)
    total_page_num = int(html.xpath('string(//span[@class="next"]/preceding-sibling::a[1])'))
    return total_page_num


def get_movie_info(page_source, headers):
    """
    获取每一部电影的详细信息
    :param page_source:导航页HTML字符串
    :param headers: 请求头
    :return:电影的全部信息
    """
    if page_source:
        html = etree.HTML(page_source)
        # 获取豆瓣top250每个页面下的电影豆瓣链接列表
        movies_link_list = html.xpath('//li//div[@class="info"]/div[@class="hd"]/a/@href')
        # 获取每个页面下的电影的代表影评
        movies_quote_list = html.xpath('//p[@class="quote"]/span[@class="inq"]/text()')
        for movie_link, movie_quote in zip(movies_link_list, movies_quote_list):
            time.sleep(0.5)  # 延迟,防屏蔽
            # 获取每一部电影的详细页面
            _page_source = get_page_source(movie_link, headers)
            if _page_source:
                html = etree.HTML(_page_source)
                # 新建列表,用于存储导演、编剧、主演、类型、制片国家/地区、语言、上映日期、片长、又名、IMDb链接的具体信息
                movie_info_list = [a for a in re.split(r'\n        ', html.xpath('string(//div[@id="info"])').strip())
                                   if bool(a)]
                # 将影评添加到movie_info_list的最后
                movie_info_list.append('影评:' + movie_quote)
                # 获取电影排名
                movie_rank = r'电影排名:{}'.format(html.xpath('string(//div[@class="top250"]/span[@class="top250-no"])'))
                # 获取电影名称
                movie_name = r'电影名称:{}'.format(html.xpath('string(//span[@property="v:itemreviewed"])'))
                # 获取电影链接
                movie_link = r'电影链接:{}'.format(movie_link)
                # 获取电影评分
                movie_score = r'电影评分:{}'.format(html.xpath('string(//strong[@property="v:average"])'))
                # 获取电影评价总人数
                movie_evaluated_people = r'电影评价人数:{}'.format(html.xpath('string(//a[@class="rating_people"])'))
                # 新建列表,存储电影其他信息
                movie_other_info_list = [
                    movie_rank, movie_name, movie_link, movie_score, movie_evaluated_people,
                ]
                # 获取电影5个评价星级
                movie_stars_list = [i.strip() for i in
                                    html.xpath('//div[@class="item"]//span[starts-with(@class, "stars")]/text()')]
                # 获取电影5个评价星级对应的评价人数的百分比
                movie_evaluated_per_list = html.xpath('//div[@class="item"]//span[@class="rating_per"]/text()')
                # 将电影5个评价星级及对应评价人数写入列表
                for each in zip(movie_stars_list, movie_evaluated_per_list):
                    movie_other_info_list.append('{}评价人数:{}'.format(*each))
                # 合并电影的详细信息
                movie_other_info_list.extend(movie_info_list)
                yield movie_other_info_list
                print(
                    '已经写入第{}部电影\t{}\t的信息'.format(html.xpath('string(//div[@class="top250"]/span[@class="top250-no"])'),
                                                 html.xpath('string(//span[@property="v:itemreviewed"])')))


def save_to_json(content, file_name):
    """
    保存到JSON文件
    :param content: 电影信息
    :param file_name: 文件名
    :return:
    """
    with open(file_name, 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, indent=4, ensure_ascii=False))
        f.write('\n' * 2)


def main():
    file_name = r'top250.json'
    url = r'https://movie.douban.com/top250'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0',
    }
    page_source = get_page_source(url, headers)
    total_page_num = get_page_num(page_source)
    for each_page in range(total_page_num):
        url = 'https://movie.douban.com/top250?start={}'.format(each_page * 25)
        page_source = get_page_source(url, headers)
        for _movie_info in get_movie_info(page_source, headers):
            save_to_json(_movie_info, file_name)


if __name__ == "__main__":
    print('----------爬取开始----------')
    main()
    print('豆瓣电影排行榜前250的电影信息写入完毕')

你可能感兴趣的:(爬虫)