Python爬虫实战(4) | 爬取历年中国电影票房排行榜

简介: 看了看后台,发现之前写的几篇有关爬虫实战的文章特别受欢迎,阅读量都是好几千那种然后回头发现自己好久没写爬虫了,刚好写了个小小的爬虫 demo ,今天分享给大家

附上官网地址

中国历年电影票房(http://www.boxofficecn.com/boxofficecn)

需求分析

我们先来看一下需求

  1. 获取自1994年至2022年之间,各年度的大陆票房情况,包括电影名称和票房总额
  2. 各个年度的电影票房情况分别保存至以本年度为名称的CSV文件,例如2022年电影票房数据保存到2022.csv

我们发现,中国历年来的电影票房都对应着一个 url,而且这个 url 是有规律的

例如:

1994年的中国大陆电影票房网址:http://www.boxofficecn.com/boxoffice1994

1995年的中国大陆电影票房网址:http://www.boxofficecn.com/boxoffice1995

网页分析

在知道了网址的规律之后,我们对网页进行一下分析

我们按 F12 进入网页代码查看器,当前页面的代码结构如下图
image-20221214110757437.png
可以看到电影的信息都存放在

年份、票房、电影名称以及序号都在

标签里面

代码实现

既然知道了我们要获取的信息的所在标签中,那么就开始我们的爬取过程吧!

需要导入的库文件

import requests
import bs4

将当前网页获取下来

注意:因为网页中含有中文字符,所以我们在下载网页源码之前先看下它的编码格式,输入当前网页的编码格式 print(res.encoding)

可以看到是 UTF-8 编码格式,所以我们将网页源码获取之后要对其进行编码 encode('UTF-8')

def get_web(url):
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.59"}
    res = requests.get(url, headers=header, timeout=5)
    # 查看当前网页的编码格式
    print(res.encoding)

    #对网页源码进行编码
    content = res.text.encode('UTF-8')
    return content

从网页源码中获取所需标签信息

将网页下载获取下来之后,我们使用 bs4 模块来进行解析并获取我们所需要的数据信息

soup = bs4.BeautifulSoup(content, 'lxml')
movie_list = soup.find_all('tr', attrs={'align': 'left'})

这里我定义了一个 movie_list 去存放票房信息

image-20221214111940476.png
可以看到 movie_list 是一个 bs4.element.ResultSet 对象,我们需要对其进行遍历才能获得里面的元素

print(type(movie_list))

##结果
<class 'bs4.element.ResultSet'>

信息处理

遍历获取 movie_list 中的元素并且对其进行处理,然后存放到列表 list 中

list = []
for i in movie_list:
    i = i.text.split('\n')
    i = i[1:len(i)-1]
    list.append(i)

list 中的元素如下所示:

[['1', '1995', '真实的谎言', '10300'], ['2', '1995', '红番区', '9500'], ['3', '1995', '阳光灿烂的日子', '5000'], ['4', '1995', '虎胆龙威3', '4700'], ['5', '1995', '狮子王(1994)', '4130'], ['6', '1995', '红粉', '4000'], ['7', '1995', '红樱桃', '4000'], ['8', '1995', '生死时速', '3780'], ['9', '1995', '七七事变', '3300'], ['10', '1995', '绝地战警', '3280'], ['11', '1995', '阿甘正传', '1960']]

接着我们将 list 中的内容以键值对的形式保存,方便信息的阅读性

我们以电影序号作为唯一的key

dic = {}
for i in list:
    dic[i[0]] = {'年份': i[1], '电影名称': i[2], '票房(万元)': i[3]}
return dic

数据保存

我们将字典中的内容保存到本地的 csv 文件中

def data_save(dic,year):
    file_name = 'D:\movie\\' + str(year) + '.csv'
    with open(file_name, 'w+') as f:
        f.write('序号,年份,电影名称,票房(万元)\n')
        for k, v in dic.items():
            f.write(k+','+v['年份']+','+v['电影名称']+','+v['票房(万元)']+'\n')

补充:

def data_save(dic,year):
    file_name = 'D:\movie\\' + str(year) + '.csv'
    with open(file_name, 'w+') as f:
        f.write('序号,年份,电影名称,票房(万元)\n')
        for k, v in dic.items():
            f.write(k+','+v['年份']+','+v['电影名称']+','+v['票房(万元)']+'\n')

刚开始用上面这段代码实现的时候报错

UnicodeEncodeError: 'gbk' codec can't encode character u'\xa0' in position 12:illegal multibyte sequence

出现 UnicodeEncodeError ,说明是 Unicode 编码问题, ‘gbk’ codec can’t encode character –> 说明是将Unicode字符编码为GBK时候出现的问题;

此时,往往最大的可能就是,本身Unicode类型的字符中,包含了一些无法转换为GBK编码的一些字符

unicode中的‘\xa0’字符在转换成gbk编码时会出现问题,gbk无法转换'\xa0'字符。
所以,在转换的时候必需进行一些前置动作,例如将这些字符替换成空格

.replace(u'\xa0', u' ')  

后面在演示的时候分别又报了如下报错

UnicodeEncodeError: 'gbk' codec can't encode character '\u200e' in position 13: illegal multibyte sequence


UnicodeEncodeError: 'gbk' codec can't encode character '\u200b' in position 13: illegal multibyte sequence

有了上面的经验,我们只需要把对应无法转换的字符替换成空格即可

replace(u'\u200b', u' ')

replace(u'\u200e', u' ')

最后代码如下所示:

def get_content(url):
    content = get_web(url)
    list = parse_content(content)
    dic = {}
    for i in list:
        i[1] = i[1].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        i[2] = i[2].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        i[3] = i[3].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        dic[i[0]] = {'年份': i[1], '电影名称': i[2], '票房(万元)': i[3]}
    return dic

结果展示
image-20221214113141351.png
image-20221214113158609.png
image-20221214133807742.png

  • 完整代码
import requests
import bs4

'''
去访问对应的网页并将网页源码下载下来
需要注意网页的编码格式
'''
def get_web(url):
    header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Edg/91.0.864.59"}
    res = requests.get(url, headers=header, timeout=5)
    # 查看当前网页的编码格式
    # print(res.encoding)

    #对网页源码进行编码
    content = res.text.encode('UTF-8')
    return content

'''
对下载下来的网页源码进行解析,然后获取指定内容并存放到一个列表里
'''
def parse_content(content):
    soup = bs4.BeautifulSoup(content, 'lxml')
    movie_list = soup.find_all('tr', attrs={'align': 'left'})
    list = []
    for i in movie_list:
        i = i.text.split('\n')
        i = i[1:len(i)-1]
        list.append(i)

    return list

'''
将列表中的内容转换成字典,以键值对的形式存放
'''
def get_content(url):
    content = get_web(url)
    list = parse_content(content)
    dic = {}
    for i in list:
        i[1] = i[1].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        i[2] = i[2].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        i[3] = i[3].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        dic[i[0]] = {'年份': i[1], '电影名称': i[2], '票房(万元)': i[3]}
    return dic

'''
数据保存
'''
def data_save(dic,year):
    file_name = 'D:\movie\\' + str(year) + '.csv'
    with open(file_name, 'w+') as f:
        f.write('序号,年份,电影名称,票房(万元)\n')
        for k, v in dic.items():
            f.write(k+','+v['年份']+','+v['电影名称']+','+v['票房(万元)']+'\n')


if __name__ == '__main__':
    url = 'http://www.boxofficecn.com/boxoffice'
    for year in range(1994, 2023):
        new_url = url + str(year)
        dic = get_content(new_url)
        print('_____开始获取%s年的票房信息______' %(year))
        data_save(dic, year)
        print('_____获取完成!______')
import requests
import bs4
import sys
import time

'''
根据url访问对应的网页并将网页源码下载下来
'''
def webDownload(year):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
    url = 'http://www.boxofficecn.com/boxoffice'+str(year)
    response = requests.get(url, headers=headers, timeout=4)
    content = response.text.encode('UTF-8')
    return content


'''
对爬取到的网页内容进行处理——解析和转换成字典形式
'''
def processContent(year):
    content = webDownload(year)

    movie_list = []
    soup = bs4.BeautifulSoup(content, 'lxml')
    list = soup.find_all('tr', attrs={'align': 'left'})
    for i in list:
        movie_list.append(i.text.split('\n')[1:-1])

    movie_dic = {}
    for i in movie_list:
        i[1] = i[1].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        i[2] = i[2].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ')
        i[3] = i[3].replace(u'\xa0', u' ').replace(u'\u200b', u' ').replace(u'\u200e', u' ').replace('–', 'null')
        movie_dic[i[0]] = {'年份': i[1], '电影名称': i[2], '票房(万元)': i[3]}
    return movie_dic


'''
将获取到的历年大陆票房数据保存到本地csv文件
'''
def data2csv(dic,year):
    file_name = 'E:\\movie\\' + str(year) + '.csv'
    with open(file_name, 'w+') as file:
        file.write('名次,年份,电影名称,票房(万元)\n')
        for k, v in dic.items():
            file.write(k+','+v['年份']+','+v['电影名称']+','+v['票房(万元)']+'\n')


if __name__ == '__main__':
    for year in range(1994, 2023):
        dic = processContent(year)
        print('\n_____开始获取%s年的票房信息______' %(year))
        data2csv(dic, year)
        for i in range(1, 101):
            print("\r", end="")
            print("进度: {}%: ".format(i), "▓" * (i // 2), end="")
            sys.stdout.flush()
            time.sleep(0.05)
    print('\n获取完成!')
相关文章
|
23天前
|
数据采集 JSON 算法
Python爬虫——基于JWT的模拟登录爬取实战
Python爬虫——基于JWT的模拟登录爬取实战
39 1
Python爬虫——基于JWT的模拟登录爬取实战
|
2天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第24天】本文将带你进入Python的世界,从最基础的语法开始,逐步深入到实际的项目应用。我们将一起探索Python的强大功能和灵活性,无论你是编程新手还是有经验的开发者,都能在这篇文章中找到有价值的内容。让我们一起开启Python的奇妙之旅吧!
|
2天前
|
JavaScript 数据安全/隐私保护 Python
python爬取m3u8实战!!
本文详细介绍了如何抓取和处理m3u8视频文件,包括从网页源代码中提取m3u8文件地址、下载m3u8文件及其对应的ts片段、处理加密的ts文件以及使用ffmpeg合并视频片段。通过多线程下载和文件路径处理,确保了高效和准确的视频抓取与合并。文中还提供了具体的Python代码示例,帮助读者理解和实现整个过程。
14 1
|
15天前
|
机器学习/深度学习 数据挖掘 Serverless
手把手教你全面评估机器学习模型性能:从选择正确评价指标到使用Python与Scikit-learn进行实战演练的详细指南
【10月更文挑战第10天】评估机器学习模型性能是开发流程的关键,涉及准确性、可解释性、运行速度等多方面考量。不同任务(如分类、回归)采用不同评价指标,如准确率、F1分数、MSE等。示例代码展示了使用Scikit-learn库评估逻辑回归模型的过程,包括数据准备、模型训练、性能评估及交叉验证。
37 1
|
17天前
|
调度 开发者 Python
探索Python中的异步编程:从基础到实战
【10月更文挑战第9天】在Python的世界中,异步编程是一个让开发者既能提升应用性能又能保持代码可读性的强大工具。本文将带你一探究竟,从理解异步编程的基本概念开始,到深入剖析其背后的原理,再到通过实际代码示例掌握其应用技巧。无论你是异步编程的新手还是希望深化理解的老手,这篇文章都将为你打开一扇新的大门,让你的项目因使用异步而更加高效和强大。
|
22天前
|
存储 人工智能 Java
Python编程入门:从基础到实战
【10月更文挑战第4天】本文旨在为初学者提供一个全面而深入的Python编程学习路径。我们将从Python的基本语法和概念开始,然后逐步深入到更复杂的主题,如数据结构、面向对象编程和异常处理等。最后,我们将通过一些实际的项目案例,帮助读者将理论知识应用到实践中去。无论你是编程新手,还是有一定经验的开发者,都可以在这篇文章中找到适合自己的学习内容。让我们一起开启Python编程的学习之旅吧!
|
24天前
|
人工智能 数据挖掘 Serverless
探索Python编程:从基础到实战
【10月更文挑战第2天】本文将带你走进Python的世界,了解它的基本语法、数据结构、函数等核心概念,并通过实例演示如何应用这些知识解决实际问题。无论你是编程新手还是有一定经验的开发者,都能在这篇文章中找到有价值的内容。让我们一起开启Python编程之旅吧!
|
22天前
|
数据挖掘 程序员 调度
探索Python的并发编程:线程与进程的实战应用
【10月更文挑战第4天】 本文深入探讨了Python中实现并发编程的两种主要方式——线程和进程,通过对比分析它们的特点、适用场景以及在实际编程中的应用,为读者提供清晰的指导。同时,文章还介绍了一些高级并发模型如协程,并给出了性能优化的建议。
22 3
|
24天前
|
Linux 开发者 iOS开发
Python系统调用实战:如何在不同操作系统间游刃有余🐟
【10月更文挑战第2天】Python 以其卓越的跨平台能力和丰富的标准库,成为解决多操作系统环境下编程挑战的理想选择。本文将通过实际例子展示 Python 如何简化跨平台开发。从文件系统操作到系统调用,再到 GUI 应用开发,Python 提供了多种工具和模块,如 `os`、`pathlib` 和 `subprocess`,帮助开发者轻松应对不同平台间的差异,让你成为真正的跨平台高手。
16 5
|
21天前
|
数据采集 程序员 开发者
Python编程入门:从基础到实战
【10月更文挑战第5天】本文旨在为初学者提供一条清晰的Python学习路径,涵盖基础知识、关键概念、实战项目以及常见问题解答。我们将通过简单易懂的语言和实际代码示例,帮助读者快速掌握Python编程技能。无论你是零基础的新手还是有一定经验的开发者,都能在这篇文章中找到有价值的信息。让我们一起开启Python编程之旅吧!