Python模块selenium实例:电影分类排名数据生成json,sqlite和excel(openpyxl)文件(一)
Python中的selenium模块是可以启动浏览器与人交互。我们知道requests模块在网页下载时配合上BeautifluSoup会简单很多,但是随着很多网站越来越注重反爬,会拒绝提供页面,而selenium模块通过启动浏览器像和普通浏览器一样的流量模式使你更容易被接受下载信息,同时长期有效性也会大很多。
这次我们的实例是通过爬取网站IMDb获取电影分类排名数据。需要说明的是这个网站在我们国内登录会有些困难,但是会登的上去,只是没那么顺畅。
同样首先我们先确定好我们的任务:
- selenium模块应用的前期准备。
- IMDb网页分析。
- 通过selenium获取想要的数据信息。
- 将信息格式化。
- 格式化后的信息存储到json,sqlite及excel中。
为此我们需要完成以下操作:
- selenium模块安装及安装浏览器的webdriver。
- 确定电影排名的网址以及网页源代码(html)内信息所在的元素。
- 通过find_elements_*方法寻找元素并通过.text方法获取元素内文本。
- 通过对爬取的文本进行格式化为字典模式并添加到列表中方便处理。
- 通过json将每个类别的电影数据分别写入一个json文件,然后将所有的电影汇总写入一个json文件,最后通过sqlite3,openpyxl模块将所有的json文件写入sqlite及excel文件中。
由于内容较多我们分两篇来练习,今天就先完成1-4部分。话不多说就开始练习吧。
首先,准备工作,安装selenium模块这个就不赘述了,大家自行安装。
其次准备工作的另外一项是安装相应的浏览器的webdriver,我自己用的是chrome浏览器,所以需要去ChromePriver下载Windows系统的版本,然后将chromedriver.exe添加到PATH路径上。如果你用的其它浏览器如Firefox,请自行去下载相应的webdriver并添加到环境变量中。
接下来到了分析电影网站的步骤,我们先打开其主页,点击menu中IMDb Top 250 Movies的选项进入top250排名页面会发现此页上的电影排名并没有详细的信息,而且是个总的排名,但是我们注意到页面右边有Top Rated Movies by Genre,这表示每个分类的电影排名,先点击Action动作片分类,进去页面这里提供给我们的信息有:这个排名是在每部至少出租数25000,按照降序排列,每页有50部,默认的是按照IMDb评分排列的,并且有每部电影的详细信息如时长,评分,媒体评分,电影简介,导演,演员,投票数,票房等,这正是我们所需要的,Perfect!
再来分析分析网址的构成,网址如下:
https://www.imdb.com/search/title/?genres=action&sort=user_rating,desc&title_type=feature&title_type=25000,&pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=5aab685f-35eb-40f3-95f7-c53f09d542c3&pf_rd_r=KXNCSE4DS589EV2SE77Q&pf_rd_s=right-6&pf_rd_t=15506&pf_rd_i=top&ref_=chttp_gnr_1
我们看下问号后面的部分,看着挺长,但是我们需要的是
genres,sort,title_type,title_type,同时还有个start表示从第几个开始,上面提到了一页有50个电影,所以start=51则表示第二页,以此类推。
所以我们需要请求的网址为:
https://www.imdb.com/search/title/?genres=action&sort=user_rating,desc&title_type=feature&title_type=25000,&start=1。
网址确定了,下面分析网页的元素,F12打开开发者工具,找到我们所需信息的元素,会发现每部电影的信息都包含在css类名为lister-item-content的div元素内。OK,至此我们完成了页面的分析,下面开始下载数据。
首先我们建立imdbmovies_ranking_bygenre.py文件,首先引入模块:
from selenium import webdriver
webdriver提供了很多寻找元素的方法如下:
#使用class类name的元素:
browser.find_element_by_class_name(name)
browser.find_elements_by_class_name(name)
#匹配css selector的元素
browser.find_element_by_css_selector(selector)
browser.find_elements_by_css_selector(selector)
#匹配id属性值的元素
browser.find_elements_by_id(id)
browser.find_elements_by_id(id)
#完全匹配提供的text的<a>元素
browser.find_element_by_link_text(text)
browser.find_elements_by_link_text(text)
#包含提供的text的<a>元素
browser.find_element_by_partial_link_text(text)
browser.find_elements_by_partial_link_text(text)
#匹配name属性值的元素
browser.find_element_by_name(name)
browser.find_elements_by_name(name)
#匹配标签name的元素
browser.find_element_by_tag_name(name)
browser.find_elements_by_tag_name(name)
需要说明的是browser.find_element和browser.find_elements的区别为,browser.find_element返回第一个匹配的元素,而browser.find_elements则包含页面中匹配的所有元素。同时除了by_tag_name不区分大小写,其它的所有参数都区分大小写。以上所有方法返回的是webelement对象,有了此对象通过text方法获取元素内的文本,所以我们的代码如下:
def movie_lst_data(genres):"""Get the data from url"""movie_lst = []for i in ['1','51']:options = webdriver.ChromeOptions()options.add_argument('lang=en_US')browser = webdriver.Chrome(chrome_options = options)start = i url = 'https://www.imdb.com/search/title?title_type=feature&num_votes=25000,&genres={}&sort=user_rating,desc&start={}&ref_=adv_nxt'\.format(genres,start)browser.get(url) elems = browser.find_elements_by_class_name('lister-item-content') for elem in elems:movie_dict = {}movie_str = elem.text#print(movie_str)
对代码进行一下说明,
options = webdriver.ChromeOptions()
options.add_argument('lang=en_US')
browser = webdriver.Chrome(chrome_options = options)
这三行是打开浏览器,我们要使浏览器用默认语言为英语的状态下打开浏览器,为什么呢,和IMDb网站的语言支持政策有关,大家可以自行去查看。
打开浏览器之后,我们需要通过browser.get(url) 输入网址并打开网页,这里把其放入for循环中,因为我想每个分类爬取100部(不想太多是鉴于这个网站打开并不顺畅),然后函数内传递类别的参数,这样就构成了我们网址,打开网页后通过browser.find_elements_by_class_name获取所有元素,再通过一个for循环遍历每个元素,然后通过text方法获取每个元素的内容(注意text方法只能获取单个元素的文本,所有我们需要遍历所有元素)。通过打印出来可以得知每个元素内的文本内容如下:
2. The Lion King (1994)\n
G | 88 min | Animation, Adventure, Drama\n
8.5 Rate this\n
88 Metascore\n
Lion prince Simba and his father are targeted by his bitter uncle, who wants to ascend the throne himself.\n
Directors: Roger Allers, Rob Minkoff | Stars: Matthew Broderick, Jeremy Irons, James Earl Jones, Whoopi Goldberg\n
Votes: 1,019,044 | Gross: $422.78M\n
这是一个字符串,所以我们要把这个字符串格式化添加到字典中去,所以后面代码如下:
...*movie_str = elem.text*# Convert str to listmovieLst = movie_str.split("\n")# Generate dictmovie_dict["Rank"] = movieLst[0].split('.')[0]if len(movieLst[0].split('.')[0]) == 3:movieName = movieLst[0][4:-7].strip()movie_dict['Movie'] = movieNameelse:movie_dict['Movie'] = movieLst[0][3:-7].strip()movie_dict['Year'] = movieLst[0][-5:-1] if len(movieLst[1].split('|'))==2:movie_dict['Duration'] = movieLst[1].split('|')[0].strip()movie_dict['Movie Genres'] = movieLst[1].split('|')[1].strip()elif len(movieLst[1].split('|'))==3:movie_dict['Duration'] = movieLst[1].split('|')[1].strip()movie_dict['Movie Genres'] = movieLst[1].split('|')[2].strip()movie_dict['IMDb Score'] = movieLst[2].split(' ')[0]if len (movieLst) == 7:movie_dict['Metascore'] = movieLst[3].split(' ')[0]movie_dict['Plot'] = movieLst[4]movie_dict['Director'] = movieLst[5].split('|')[0].split(":")[1].strip()movie_dict['Stars'] = movieLst[5].split('|')[1].split(":")[1].strip()if "|"in movieLst[6]:movie_dict['Votes'] = movieLst[6].split('|')[0].split(":")[1].strip()movie_dict['Gross'] = movieLst[6].split('|')[1].split(":")[1].strip()else:movie_dict['Votes'] = movieLst[6].split('|')[0].split(":")[1].strip()movie_dict['Gross'] = "NO DATA"elif len (movieLst) == 6: movie_dict['Metascore'] = "NO DATA"movie_dict['Plot'] = movieLst[3]movie_dict['Director'] = movieLst[4].split('|')[0].split(":")[1].strip()movie_dict['Stars'] = movieLst[4].split('|')[1].split(":")[1].strip()if "|"in movieLst[5]:movie_dict['Votes'] = movieLst[5].split('|')[0].split(":")[1].strip()movie_dict['Gross'] = movieLst[5].split('|')[1].split(":")[1].strip()else:movie_dict['Votes'] = movieLst[5].split('|')[0].split(":")[1].strip()movie_dict['Gross'] = "NO DATA" movie_lst.append(movie_dict)
上述代码中我们首先把每个字符转为列表,然后把每项信息添加到字典中,注意的是列表中有些元素会有些变化,例如媒体评分若是没有则列表的长度就会变为6,而包含时长的元素通过“|”分出的列表长度会有两种情况,还有有些电影没有票房数据等等这些都会影响我们对列表的引用,所以要把数据进行周全的分析以避免错误。
运行无误后每部电影的信息如下所示的字典格式添加到了列表中:
[
{"Rank": "1","Movie": "K.G.F: Chapter 2","Year": "2022","Duration": "168 min","Movie Genres": "Action, Crime, Drama","IMDb Score": "9.0","Metascore": "NO DATA","Plot": "In the blood-soaked Kolar Gold Fields, Rocky's name strikes fear into his foes. While his allies look up to him, the government sees him as a threat to law and order. Rocky must battle threats from all sides for unchallenged supremacy.","Director": "Prashanth Neel","Stars": "Yash, Sanjay Dutt, Srinidhi Shetty, Raveena Tandon","Votes": "78,538","Gross": "NO DATA"
},
......
注意每个页面数据下载完成后要关闭浏览器,不然要打开很多个。最后我们的函数返回我们下载完成的列表:
......browser.close()# print(elem.text)return movie_lst
然后我们再建立一个函数,将每部电影的数据写入一个json文件中:
def movie_json_data(movie_lst,genres):"""Generate the json data"""with open('json_data/{}_movies(100).json'.format(genres), 'w',encoding='utf-8') as json_file:json.dump(movie_lst, json_file, indent=4, ensure_ascii=False)
最后运行函数:
if __name__ == "__main__":try:"""genres = ['Action','Adventure','Animation''Biography','Comedy','Crime','Drama','Family','Fantasy','Film_Noir','History','Horror','Music','Musical','Mystery','Romance','Sci_Fi','Sport','Thriller','War','Western',]"""genres = "Action"movie_lst = movie_lst_data(genres) movie_json_data(movie_lst,genres)except Exception as e:print("ERROR: "+ str(e))
这里需要说明的是,本来类别也可以通过for循环类别列表自动完成,但是考虑到这个网站的登录变数较大,所以还是手动运行每个类别比较好。链接不上的情况下程序会退出,这时要重新运行,有时候需要运行多几次才能成功,如Action类别的电影成功运行如下图所示:
每个网页运行完成后会自动关闭浏览器,然后再次打开第二页,完成后再次关闭,最后数据都写入json文件,当所有的类别都完成后我们会看到我们的文件夹内生成了所有的类别电影的排名100的文件,
而生成的json文件内容如下:
至此我们前4项的工作和生成json文件部分部分也就完成了,这也我们这个实例的第一部分。
后面第二部分我们会将每个类别的电影数据汇聚成一个按照IMDb分数排行总数据写入json,同时将所有的json数据写入到sqliet和excel中去。
(本来文章有很多图片展示的,但图片多了总是待审核,所以无奈删除了一些)
未完待续…
Python模块selenium实例:电影分类排名数据生成json,sqlite和excel(openpyxl)文件(一)相关推荐
- B站路飞学城学习笔记-Python爬虫-爬取电影分类排名-
一.过程分析 1.先打开douban电影排行榜,点击喜剧部分 2.用鼠标滚轮向下翻页,同时按f12进行检查,点击Network中的Headers 3.我们可以发现Headers中有很多信息,比如Req ...
- boost::python模块实现使用原始指针访问数据的示例
boost::python模块实现使用原始指针访问数据的示例 实现功能 C++实现代码 实现功能 boost::python模块实现使用原始指针访问数据的示例 C++实现代码 #include < ...
- Python学习笔记_1_基础_2:数据运算、bytes数据类型、.pyc文件(什么鬼)
Python学习笔记_1_基础_2:数据运算.bytes数据类型..pyc文件(什么鬼) 一.数据运算 Python数据运算感觉和C++,Java没有太大的差异,百度一大堆,这里就不想写了.比较有意思 ...
- 在Ubuntu 14.04.5 LTS上安装python模块selenium 3实录
简介 Selenium是python模块库中一组web自动化测试工具集,提供多种语言的API,例如java,python,ruby,.net等,支持Firefox,Chrome,IE,Safari 等 ...
- Python爬虫入门实例八之股票数据定向爬取并保存(优化版)
文章目录 写在前面 一.准备工作 1.功能描述 2.候选数据网站的选择 3.程序的结构设计 4.本篇选取的数据网站 (1)网站链接 (2)网站内容 二.数据网站分析 1.股票列表的分析 2.个股信息的 ...
- Python网络爬虫实例1:股票数据定向爬虫
Python网络爬虫实例:股票数据定向爬虫 一.功能描述 目标:获取上交所和深交所所有股票的名称和交易信息 输出:保存到文件中 技术路线:requests-bs4-re 二.候选数据网站选择 候选网站 ...
- 时间序列python复杂网络实例_基于时间序列数据的复杂网络重构
摘要:现实生活中,复杂系统俯首即是,和人们的生活息息相关,遍及的领域包括社会,经济,物理,生物和生态等.为了便于研究,复杂网络通常被看成是复杂系统的一种抽象描述,其中,网络中的单个节点对应于系统中的单 ...
- python制作考试系统_python测试框架数据生成工具最全资源汇总
xUnit frameworks 单元测试框架 frameworks 框架 unittest - python自带的单元测试库,开箱即用 unittest2 - 加强版的单元测试框架,适用于Pytho ...
- php 生成复杂json数据,生成json的几种方式
这里是修真院后端小课堂,每篇分享文从 [背景介绍][知识剖析][常见问题][解决方案][编码实战][扩展思考][更多讨论][参考文献] 八个方面深度解析后端知识/技能,本篇分享的是: [生成json的 ...
- vue读取excel表格数据_vue 利用 js-xslx 读取 excel 表格文件
文件读取~~~ 表格数据 excel读取数据.jpg // template // 文件选择,或者使用原生 imput type 为 file action="/" :on-cha ...
最新文章
- 计算机分级存储的特,一种分级存储的方法、系统、设备及介质技术方案
- 科研人必备的学术导航,不看后悔!
- Jzoj5317 Func
- OSPF高级特性——LSA-3(Network Summary LSA)的过滤、路由协议——管理距离的修改、外部路由的metric值的修改
- 谁记录了mysql error log中的超长信息
- 第一章 Javscript的数据类型
- gcc -fomit-frame-pointer选项,-fno-dwarf2-cfi-asm 选项
- 华为云Centos7搭建hadoop集群一:云服务器准备
- c语言练习----渔夫打鱼晒网
- 新媒体运营之如何低成本,有效地进行企业公众号拉新,获取10万+潜在用户? 黎想
- b、B、kb、kB单位
- Solidity ——push mapping 探赜索隐
- Halcon学习笔记之测量系列-卡尺测量
- 【时间从来不语,却回答了所有问题】读书摘记
- [奔跑吧 Linux内核][学习记录]编译内核-实验1-2-[环境以及参考]
- 交易老手交易老手的最终境界:坚持做正确的事情,不要在乎一笔输赢
- layui文件上传重复问题
- 自定义视频播放器与慢放滚轮
- 51nod 1515 明辨是非 2017百度之星初赛第一场第二题(并查集+启发式合并)
- 巧解异或操作的逆运算——位运算结合律
热门文章
- 【大数据实战】招聘网站职位分析
- python视频字幕处理_用Python处理字幕文件
- 利用Android SAF(存储访问框架)进行游戏反和谐(伊甸园的骄傲)/Android data目录的访问限制
- pygame基本实现塔防游戏
- diskgenius给C盘扩容总结
- vue中使用video插件在微信浏览器中视频无法自动播放的问题
- 免费且快速搭建个人www服务器的教程
- 安踏的搜索引擎营销_案例:从安踏看IP跨界营销的内在逻辑
- 使用Spring Validation 完成后端数据校验
- qq邮箱发送邮件服务器类型,设置QQ邮箱为发送邮件服务器的详细带图步骤