获取豆瓣网1980-2010年电影详情

#coding=utf-8
'''
爬虫豆瓣电影,支持分年代爬取
'''

import time
import requests
import os
import re
import json
import Save_Data
import logging


#定义日志级别及日志文件名
logging.basicConfig(
    # 日志级别
    level = "ERROR",
    # 日志打印时间格式
    datefmt = "%Y-%m-%d %H:%M:%S",
    # 日志打印内容格式
    format = '%(asctime)s %(filename)s[line:%(lineno)d] %(message)s',
    # 日志输出到文件
    filename = ("log_2010.txt"),
    # 覆盖模式
    filemode = 'w'
)

# 定义请求头
headers = {
    "Referer":"https://movie.douban.com/explore",
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
}

# 定义获取年份的时间区间
year_dict = {
    "80年代":"1980,1989",
    "90年代":"1990,1999",
    "2000年代":"2000,2009",
    "2010年代":"2010,2019",
}

# 定义各个年代获取的电影页数
max_page = {
    "80年代":"376",
    "90年代":"752",
    "2000年代":"1342",
    "2010年代":"2315",
}


def get_doubanmovie_index(time_start,idx,headers):
    '''
    获取电影类别页面内容
    :param movie_type:电影类别
    :param headers:请求头部信息
    :return:电影类别页面数据
    '''
    global proxy
    proxy= ''
    my_proxy = {
        'http': 'http://' + proxy,
        'https': 'https://' + proxy,
    }
    logging.error(proxy)
    logging.error(my_proxy)
    # page_idx = idx * 20
    url = "https://movie.douban.com/j/new_search_subjects?" \
          "sort=U&range=0,10&tags=%E5%8A%A8%E6%BC%AB&start={}" \
          "&countries=%E6%97%A5%E6%9C%AC&year_range={}".format(idx,time_start)
    try:
        logging.error(my_proxy)
        ret = requests.get(url,headers=headers,timeout=(2,4))
        # ret.raise_for_status()  #判断http头中的状态码是否为200
    except:
        print("获取电影:%s 页面内容出错;url:%s"%(time_start,url))
        logging.error("获取电影:%s 页面内容出错;url:%s"%(time_start,url))
        logging.error('')
        return ""
    return ret.text

def get_movie_list(data):
    '''
    解析电影页面数据,主要为了获取电影名称及电影详情页url
    :param data:电影类别页面数据
    :return:电影名称及电影详情页url
    '''
    movie_list = []
    try:
        tmp_data = json.loads(data)
        subjects_data = tmp_data["data"]
        for i in subjects_data:
            movice_name = i["title"]
            movie_url = i["url"]
            movie_list.append([movice_name,movie_url])
    except:
        print("获取电影名称及电影详情页失败~")
        logging.error("获取电影名称及电影详情页失败~")
        logging.error(data)
    if len(movie_list) == 0:
        logging.error(data)
        return []
    return movie_list

def movie_content_page(url,headers):
    '''
    获取电影详情页内容
    :param url:电影详情页url
    :param headers:请求头
    :return:电影详情页数据
    '''
    global proxy
    my_proxy = {
        'http': 'http://' + proxy,
        'https': 'https://' + proxy,
    }
    logging.error(proxy)
    logging.error(my_proxy)
    try:
        logging.error(my_proxy)
        ret = requests.get(url,headers = headers,timeout=(2,4))
        # ret.raise_for_status()
    except:
        # proxy = MyProxy.get_proxy()
        print("获取电影详情页失败,url:%s"%url)
        logging.error("获取电影详情页失败,url:%s"%url)
        logging.error('')
        return ""
    return ret.text

def handle_movie_data(data):
    '''
    解析电影详情页数据,提取演员表、剧情介绍
    :param data:电影详情页所有数据
    :return:电影演员表
    :return:电影剧情介绍
    '''
    movie_info = []
    mark_pattern = re.compile('property=\"v:average\">(.*?)</strong>')
    mark_and_count = re.findall(mark_pattern,data)
    count_pattern = re.compile('property=\"v:votes\">(.*?)</span>')
    count = re.findall(count_pattern,data)
    movie_year_pattern = re.compile('\"datePublished\".*?:.*?\"(.*?)\"')
    movie_name_pattern = re.compile('property=\"v:itemreviewed\">(.*?)</span>')
    movie_name = re.findall(movie_name_pattern,data)
    movie_year_bk = re.findall('class=\"year\">(.*?)</span>',data)
    movie_year = re.findall(movie_year_pattern,data)
    try:
        #电影名称
        _name = (movie_name[0])
    except:
        _name = ""
    try:
        # 电影年份
        _year_bk = (str(movie_year_bk[0]).replace("(","").replace(")",""))
    except:
        _year_bk = ""
    try:
        _year = (movie_year[0])
    except:
        _year = ""
    try:
        _count = (count[0])
    except:
        _count = ""
    try:
        _mark = (mark_and_count[0])
    except:
        _mark = ""
    try:
        movie_info.append([_name,_year_bk,_year,_mark,_count])
    except:
        print("err")
        logging.error("ERROR movie_name:%s movie_year:%s movie_mark:%s movie_count:%s"%(
            movie_name,
            movie_year_bk,
            movie_year,
            mark_and_count,
            count))
    return movie_info

def main(year_type,count):
    global proxy
    my_count = 1
    mk_path = '数据集' + "\\" + year_type
    # 类别文件夹如果不存在,就创建
    if not os.path.exists(mk_path):
        os.makedirs(mk_path)
    # 提取开始年份
    time_start = year_dict.get(year_type)
    for idx in range(count):
        page_idx = idx * 20
        if page_idx > int(max_page.get(year_type)):
            break
        for i in range(5):
            # 获取该类别的电影主页内容
            index_data = get_doubanmovie_index(time_start,page_idx,headers)
            # 解析该主页内容,得到["电影名称","电影详情页url"]
            movie_url_list = get_movie_list(index_data)
            if len(index_data) > 0 and len(movie_url_list) > 0:
                break
            else:
                logging.error("------------%s"%proxy)
                time.sleep(2)
            if i > 3:
                break
        logging.error("第%d页获取成功! length_html:%d"%(
            (page_idx+1),
            len(index_data)
            )
        )
        for url_list in movie_url_list:
            logging.error(url_list)
            movie_url = url_list[1]
            for i in range(5):
                # 获取电影详情页的内容
                movie_content_data = movie_content_page(movie_url, headers)
                # 获取电影演员表及剧情介绍
                movie_info_list = handle_movie_data(movie_content_data)
                if len(movie_content_data) > 0 and len(movie_info_list) > 0:
                    print('已经获取%d部电影数据'%my_count)
                    my_count += 1
                    break
                else:
                    logging.error("------------%s" % proxy)
                if i > 3:
                    break
            # 保存电影剧情介绍
            Save_Data.save_content(mk_path,movie_info_list)
            logging.error("第%d页获取成功! url:%s"%(
                (page_idx+1),
                url_list[1]
                )
            )

if __name__ == '__main__':
    if not os.path.exists('数据集'):
        os.mkdir('数据集')
    # 定义需要爬取的类别列表
    want_get_movie = ["80年代","90年代","2000年代","2010年代"]
    # 定义爬取页数,每页20条
    COUNT = 2315
    # 遍历需要爬取的类别列表
    for type_name in want_get_movie:
        main(type_name,COUNT)
        #coding=utf-8
'''
数据存储模块,保存电影数据
'''

import csv
import logging

def save_actor(file_path,data):
    '''
    保存电影演员信息
    :param file_path:保存的路径信息
    :param data: 电影演员信息
    :return:
    '''
    file_name = file_path + "\\" + "演员表.csv"  #在电影名的文件夹下,将数据保存到演员表.csv
    o_file = open(file_name,"w",newline="",encoding="utf-8-sig")
    f = csv.writer(o_file)
    for i in data:
        f.writerow(i)
    o_file.close()

def save_content(file_path,data):
    '''
    :param file_path: 保存的路径信息
    :param data: 电影信息
    :return:
    '''
    try:
        file_name = file_path + "\\" + "动漫数据.csv"
        f = open(file_name, "a", encoding="utf-8-sig",newline="")
        c_f = csv.writer(f)
        for i in data:
            c_f.writerow(i)
        f.close()
    except:
        logging.error("保存数据失败:%s"%data)

  获取豆瓣网1980-2010年电影详情获取豆瓣网1980-2010年电影详情

上一篇:零基础Python爬虫教程,入门学习的三个阶段


下一篇:React中匹配路由参数的方式