Python网络爬虫数据采集实战:豆瓣电影top250爬取

376次阅读
没有评论

目录

一、网页分析

    1.网页概览

    2.匹配分析

二、爬虫编写

    1.网页获取

    2.信息提取

    3.保存数据

    4.循环结构


 

一、网页分析

    1.网页概览

    首先在浏览器中输入以下网址打开爬取的目标网站豆瓣电影top250:https://movie.douban.com/top250?start=225&filter=,得到如下界面。

Python网络爬虫数据采集实战:豆瓣电影top250爬取

    通过查看豆瓣电影官网的robots协议,发现此网站并不在Disallow里,表明该网站不限制爬取

Python网络爬虫数据采集实战:豆瓣电影top250爬取

    2.匹配分析

    接着按下F12键查看谷歌浏览器的Devtools工具,发现第一部电影(即肖申克的救赎)的完整内容都在一个class属于"item"<div>标签中,且其后每一部电影都在相同的结构中。

Python网络爬虫数据采集实战:豆瓣电影top250爬取

    接着我们逐步通过查看源代码来进行信息匹配,通过下图可以看到在class"pic"div标签中储存了电影排名信息和图片url。

Python网络爬虫数据采集实战:豆瓣电影top250爬取

    因此我们可以利用正则表达式中的非贪婪匹配依次匹配到每个电影条目中的电影排名和图片url信息,非贪婪匹配即(.*?)的原因在于此页源代码中包含了多部电影。代码如下,第一个(.*?)即为排名,第二个(.*?)为图片url

<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?

    依次类推,名称和别名依次在class"title"<span>标签和class"other"<span>标签中,整合上面的正则表达式后代码如下:

Python网络爬虫数据采集实战:豆瓣电影top250爬取

<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">(.*?)

    接下来是导演主演年份国家类型的标签位置和正则表达式:

Python网络爬虫数据采集实战:豆瓣电影top250爬取

<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">(.*?)</span>.*?<div class="bd">.*?<p class="">(.*?)<br>(.*?)</p>.*?

    之后是评分评价人数的标签位置及整合后的正则表达式:

Python网络爬虫数据采集实战:豆瓣电影top250爬取

<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">(.*?)</span>.*?<div class="bd">.*?<p class="">(.*?)<br>(.*?)</p>.*?class="star.*?<span class="(.*?)"></span>.*?span class="rating_num".*?average">(.*?)</span>.*?<span>(.*?)</span>.*?

    最后是提取储存在class"inq"<span>标签中的经典评价内容:

Python网络爬虫数据采集实战:豆瓣电影top250爬取

<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">(.*?)</span>.*?<div class="bd">.*?<p class="">(.*?)<br>(.*?)</p>.*?class="star.*?<span class="(.*?)"></span>.*?span class="rating_num".*?average">(.*?)</span>.*?<span>(.*?)</span>.*span class="inq"?>(.*?)</span>

二、爬虫编写

    1.网页获取

    在进行上面的匹配分析之后我们得到了本文最核心的正则匹配表达式,接下来我们开始尝试写出网页获取的代码。

    首先导入相关库,之后将上述豆瓣电影top250的网址存储在url变量中,定义浏览器头,之后调用requests库的get方法获取网页源代码。

import requestsimport reimport jsonurl = "https://movie.douban.com/top250?start=0&filter="headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0" }response = requests.get(url, headers=headers)text = response.text

    2.信息提取

    接着将上文的正则表达式存储为字符串,调用re库的findall函数匹配出所有满足条件的子串

regix = '<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?' \ 'div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">(.*?)'\ '</span>.*?<div class="bd">.*?<p class="">(.*?)<br>(.*?)</p>.*?' \ 'class="star.*?<span class="(.*?)"></span>.*?span class="rating_num".*?average">(.*?)</span>.*?<span>(.*?)</span>.*?' \ 'span class="inq"?>(.*?)</span>'res = re.findall(regix, text, re.S)print(res)

    通过输出结果可知电影的排名封面url名称导演和演员评分评价评价内容都在多个元组组成的列表之中。

[('1', 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg', '肖申克的救赎', '&nbsp;/&nbsp;月黑高飞(港) / 刺激1995(台)', '\n 导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /…', '\n 1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情\n ', 'rating5-t', '9.7', '1893209人评价', '希望让人自由。'),

    由于图片文件需要单独发送请求,我们在此单独定义一个图片下载函数,调用python内置函数open将响应内容写入到jpg格式文件中。

# 定义下载图片函数def down_image(url,name,headers): r = requests.get(url,headers = headers) filename = re.search('/public/(.*?)$',url,re.S).group(1) with open("film_pic/"+name.split('/')[0]+".jpg",'wb') as f: f.write(r.content)

    在此基础上我们将上文代码整合为一个网页解析函数,此函数完成了一页中获取网页、提取信息、处理信息和输出信息的功能,此处的yield生成器能够在在一次调用过程中多次返回值,较return有明显的优势。

# 定义解析网页函数def parse_html(url): response = requests.get(url, headers=headers) text = response.text # 正则表达式头部([1:排名 2:图片] [3:名称 4:别名] [5:导演 6:年份/国家/类型] [7:评星 8:评分 9:评价人数] [10:评价]) regix = '<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?' \ 'div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">(.*?)'\ '</span>.*?<div class="bd">.*?<p class="">(.*?)<br>(.*?)</p>.*?' \ 'class="star.*?<span class="(.*?)"></span>.*?span class="rating_num".*?average">(.*?)</span>.*?<span>(.*?)</span>.*?' \ 'span class="inq"?>(.*?)</span>' # 匹配出所有结果 res = re.findall(regix, text, re.S) for item in res: rank = item[0] down_image(item[1],item[2],headers = headers) name = item[2] + ' ' + re.sub('&nbsp;','',item[3]) actor = re.sub('&nbsp;','',item[4].strip()) year = item[5].split('/')[0].strip('&nbsp;').strip() country = item[5].split('/')[1].strip('&nbsp;').strip() tp = item[5].split('/')[2].strip('&nbsp;').strip() tmp = [i for i in item[6] if i.isnumeric()] if len(tmp) == 1: score = tmp[0] + '星/' + item[7] + '分' else: score = tmp[0] + '星半/' + item[7] + '分' rev_num = item[8][:-3] inq = item[9] # 生成字典 yield { '电影名称': name, '导演和演员': actor, '类型': tp, '年份': year, '国家': country, '评分': score, '排名': rank, '评价人数': rev_num, '评价': inq }

    3.保存数据

    上文返回的格式为字典,因此我们调用json库的dumps方法将字典编码为json格式名写入到top250_douban_film.txt文本文件中。

# 定义输出函数def write_movies_file(str): with open('top250_douban_film.txt','a',encoding='utf-8') as f: f.write(json.dumps(str,ensure_ascii=False) + '\n')

    4.循环结构

    上文仅仅爬取了一页共25条数据,通过点击页面中的下一页对比发现,各页码的url仅仅是start=后面的参数不同,且都是25的倍数。

Python网络爬虫数据采集实战:豆瓣电影top250爬取

Python网络爬虫数据采集实战:豆瓣电影top250爬取

    鉴于此,我们利用循环结构和字符串拼接就可以实现多页爬取:

# 定义主函数def main(): for offset in range(0, 250, 25): url = 'https://movie.douban.com/top250?start=' + str(offset) +'&filter=' for item in parse_html(url): print(item) write_movies_file(item)

    最终爬取的封面图片及电影信息结果如下:

Python网络爬虫数据采集实战:豆瓣电影top250爬取

Python网络爬虫数据采集实战:豆瓣电影top250爬取

    至此豆瓣电影top250爬取实战结束~爬虫完整代码可以在公众号中回复top250”获得。当然一个爬虫远远不能让笔者和大家熟练,要想举一反三还需要去反复体会案例中的分析思路具体解决途径

    因此我们对上述爬虫做一下总结:在爬虫中首先对网页结构robots协议进行分析,得到正则匹配表达式,再利用requests库对目标网页发起请求,再用re库及正则匹配表达式对目标网页源代码进行信息提取,之后利用json库和open函数将图片及提取的信息存储起来,在最再利用循环结构字符串拼接实现翻页爬取。

    然而有些网页比如淘宝或者京东我们会发现源代码中无法提取到想要的信息,原因在于这些网站都属于动态加载的网站,而豆瓣电影网站属于静态网页,在后文中将对这些技术进行进一步的讲解。前文涉及的基础知识可参考下面链接:

Python网络爬虫数据采集实战:基础知识

Python网络爬虫数据采集实战:Requests和Re库

 

 

Python网络爬虫数据采集实战:豆瓣电影top250爬取

 

神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试

相关文章:

版权声明:Python教程2022-10-27发表,共计6029字。
新手QQ群:570568346,欢迎进群讨论 Python51学习