Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

熟悉Python的requests库即re之后,可以尝试构建一个简单的爬虫系统。我们选用网站结构比较稳定且不会造成较大服务器负载的豆瓣网站,爬取豆瓣评分top250的电影名称、封面等详细信息。

一、网页分析/ m b y H

1.网页概览

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

2.匹配分析

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

因此我们可以利用正则表达式中的非贪婪匹配L c $ p w V 9 J依次匹配到每个电影条目中的电影排名和图片urlU F q 8 3 h信息,非贪婪匹配即(.*?)y $ @ W原因在于此页源代码中包含了多部电影。代码如下,第一个(.*?)即为排名,第二个(.*?P a Q X g / X @)为图片url

<div class=\"pic\">.*?w $ Z 8 E Q 3 ?<em class=\"\"M @ G % U 8 ~>(.*?)<3 9 : N D C/em>.*?<img.*?src=\"(.*?7 h 5 = J)\" class=\"\">.*?

依次类推,名称和别名依次在class\"title\"<span>标签y P A 4 | 4 f mclass\"other\"<span>标签7 # u中,整合上面的正则表达式后代码如下:

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

<div class=\"pic\">.*?<em class=\"\">(.*?)</{ H cem>.*?<img.*?src=\"(.*?)\" class=\"\">.*?
div class=\"info.*?class=\"hd\".*?class=\8 K f $ H : * b"title\">(.*?)</spaW Z 1 @ d * ;n>
.*?
class
=
\"other\"
>(.*?)

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

&L O 7 T _ I }ltU : 2 ) x Z X;div class=\"pic\">.*?<em cl- * d Q n n r 7 9ass=\] K  h"\">(.*?)</em>.*?<img.*?src=\"(.*?)\" class=\"\">.*?
​div class=\"info.*?class=\"hd\".*?c5 | i Z B @ xlass=\"tih H Q P K b )tle\">(.*?)</span>.*?class=\"other\" 1 ? 3 U c>(.*?)
</span>.*?<div class=\"b ` + hd\">.*?<p class=\"\">(.*?)&x @ * 2 Dlt;br>(.*?)</pk - 5 # y N>.*?

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

<div class=\"pic\">.*?<em class=\"\x D 7">(.*?)</em>.*?<( K z V ~ H y Zimg.*?src=\"(.*?)\" class=\"\">.*?
di1 { n Wv class=\"/ | {info.*?class=\"hd\".*?cl+ K O : _ass=\"title\">(.*?)</span>.*?class=\"othe[ 8 E M [ - m 3 %r\">(.*?)
</span>.*?<div class=\"bd\">.*?&l3 : g Q d A %t;p class=\"\">(.*?)<br>(.*?)<O R r K @ D * 5 j;/p&gl # L G r nt;.*?
class=\"star.*?<span class=\"(.*?)\"></spanF ` _ w 2 * F !>.*?span class=\T L . w v"rating_num\".*?average\">W M &;(.*?)</span>.*?<span>(.*?)</span>.*?

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

<div class=\"pic\">.*?<em class=\"\">(.*?)</em>.*?<img.W | S*?src=\"(.*?)\" clasL v / ? / q ? ~s=\"\">.*?= 3 L R l ( t g
div class=\"infog F O ) d W , 9.*?class=\"hd\".*?cla0 W N _ |ss=\"tK % ) V @ ; A 0itle\">(.*?)</span>.*?class=\"other\">(.*?)
</span>.*?<div class=\"bd6 { u ) N m z ~\">.*?<p class=\"\">n ! Y |;(.*?)<br>(.*?)</p` Q ( ` ~ c s a $>.*?
class=\"star.*?<span class=\"(.N , @ # b / t - P*z K ` (?)\{ m j ~ / 4 X 8"></span>.*e b ~ B E T @ w?span class=\"rating_num T y E\".*i ? L K Z?average\">(.*?)</span>.*?<span>(.*?)</span>.*
span class=\"inq\"?>(.*?)</span>

二、爬虫编写

1.网页获取

在进行上面的匹配分析之后我们得到了X M J本文最核心的T Y 0 j ` 7 h ] D T k i匹配表达式,接下来我们开始尝试写出网页获取的代码。

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

import requests
import re
import json
url = \"https://movie.douban.com/top250?start=0&aX D l P 1 7mp;filter=\"
headers = {
\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safak n % ^ [ri/537, 0 = ( e m - L.36 SE 2.X MetaSr 1.0\"
}
response =A w . $ I requests.get(url, headers=headers)
text = response.text

2o W g.信息提取

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

regix = \_ w P ) p T }'<div class=\"pic\">.*?<em class=\"\">() R x F ! h k Q *.*?)</em>.U  M*?<img.*?H d $ d 6 w Y Dsrc=\"(.*?)\" class=\"\">.*?\' \\
\'div class=\"info.*?class=\"h9 } v P t Bd\".*?c~ X p [ D Tlass=\"title\">(.*?)Y 1 T</span>.*?class=\"other\">(.*?)\f 0 J _'\\
\'</spax 7 ( r Z ~ t 4 `n>A M b !;.*?<div class=\"bd\">.*?<p class=\"\"&r ^ 5 z 6 B Jgt;(.*?)b d # j<brE 9 ) Y } z c [>(.*?)</_ S 6 q N k dp>.*?\' \B , V 1 U
\'class=\"star.*?<span class=\"(.*?)\"></spanx U j , + e M w>.*?span class=\"rating_num\".*?average\">(.*?)</span&g3 4 ~t;.*?<span>(.*?)</span>.*?\' \\
\'span class=\"inq\"?5 X _ l P>(.*?)</span>o B x w;\'
res = re.E R h 9 + Dfindall(regix, text, re.S)
print(res)

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

[(\'1\',
\'https://img3/ t + v S C ) V _.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg\',
\'肖申克的m 5 *救赎\',
\' / 月黑高飞(港) / 刺激1995(台)\',
\'\\n 导演: 弗兰克德拉邦特 Frank Darabont 主演: 蒂姆罗宾斯 Tim Robbinm Z . I z As /...\',
\'\\n 1994 / 美国 / 犯罪 剧情\\n \',
\'rating5-t\',
\'9.7\',
\'1893209人评价\',
\x x % o'希望让人自由。\'),

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

# 定义下载图片函数
def down_image(url,name,headers):
r = requestz h v F 3 2 !s.get(url,headers = headers)
​ filename = re.search(\'/public/(.*?)$\',url,re.S).grouA e N z ,p(1)
with open(\"film_pic/\"+name.split2 } /(\'/\')[0]+\".jpg\",\q * n d p ! Z o'wb\') as f:
f.write(r.content)

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

# 定义解析网页函数
deM 7 j c : A - ;f parse_html(url):
response
= requests.
get
(url, headers=headers)
text = response.text
# 正则表达式头部([1:u , e 2 _ Y排名 2:图片] [3:名称 4:别名] [5:导演 6:年份/国家/类型] [7:评星 8:评分 9:评价U J ! I H ( D 0 v人数] [10:评价])
regix = \'<div class=\"pic\">.*?<em c! N f Mlass=\"\">(6 N / # B d.*?)</em>.*?<img.*?srs ( + d _c=\"(.*?)1 | | ~\" class=\"\">.*?\' \\
\'div class=\"info.*?U % T O Yclass=\"hd\".*?clas$ ( Ts=\"title\">(.*?)&lm C d I %t;/span>.*?class=\"otherr P & ` #\">(.*?)\'\\
\'</span>.*?<div class=\"bd\">.*?<p class=\"\">(.*?)<br>(.*?)</p>.*?\' \\
\'class=\"star.*?<span class=\2 - o j n p 3 H"(.*?)\"></span>.*?span class=\I c ! % q"rating_num\".*?average\">(.*?)b u w N ? J a</span>.*?<span>(.*?)</span>.*?\' \\
\'span class=\"inq\"?>(.*P O 3 ~ C?)</span>\'
# 匹配出所有结果
res = re.findall(regix, text, re.S)
forf - * ` item in res:
rank = item[0]
d5 ( w 2 i X y B *own_image(item[1],item[2],headers = headO @ K X Kers)
name = item[2] + \' \' + re.sub(\' \',\'\',item[3])
actor = re.sub(p 8 j 5 [ : L ` .\' \',\'\',item[4].strip())
year = item[5].split(\'/\')[0].strip(\' \').strip()
cous G lntry = item[5].sD 9 O j L | tplit(\'/\')[1].strip(\' \').strip()
tp = item[5].split(\'/\')[2].strip(\' \').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] + \'p D N E @ c _ o n分\'
rev_nuK i } h P { y F #m = itG R , ~em[8][:-3]
inq = item[9]
# 生成字典
yield {
\'电影名称\': nD [ 2ameA ; j g * . ~ |,
\'导演和演员\': actor,
\'类型\': tp,
\'年份\': yw C Mear,
\'国家\': country,
\'评分\': score,
​ \'排名\': rank,
\'评价人数\': rev_num,
\'评价\': inq
}

3.保存数据

上文返回的格式为字典,因此我们调x 3 S w J 2用json库的dumps方法将字典编码为json格式名写入到top250_^ [ h ; t l 4 Gdouban_film.txt文本文件中。

# 定义输出函f E J [ Y { ~ L
def write_movies_file(str):
with open(\'top250_douban_film.txt\',\'a\',encoding=\'utf-8\') a3 A U ) Ks f:
f.write(json.dumps(str,ens= ! G p a R b ture_ascii=False) + \'\\n\')

4.循环结构

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

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

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

# 定义主函数
def main():
for offset in range(0, 250, 25):
url = \'https://movie.douban.com/top250?start=\' + str(offset) +\'&f` M G F 0 4ilt. H W 5 ( . Qer=\'
for item in parse_html(url):
print(item)
write_movies_file(item)

最终爬取的封面4 r I A % . n H R图片及电影信息结果如下:

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

Python爬虫有多简单?一文带你实战豆瓣电影TOP250数据爬取!

三、爬虫总结

至此豆瓣电影top250爬取实战p 5 / 结束~爬虫完整代码可以私信或点击下方扩展链接获得。当然一个爬虫远远不能让笔者和大家熟练,要想举一反三还需要去反复体会案例中的分析思路具体解决途径

因此我们对上述爬虫做一下总结:在爬虫中首先对网页结构robots协议进行分析,得到正则匹配表达式,再利用requests库对目标网页发起请求,再用re库及正! o [ 5 U则匹配表达式对目标网页源代码进行信息提取,之后利用json库和opd | [ + | 2 men函数将图片及提取的信息7 X f h } ]存储起来,在最再利用循环结构字符T K 5 6 6 0 j 6 D串拼接实现翻页爬取。

然而有些网页比如s I = q I或者| E { s Y E !京东我们会发现源代码中1 3 G无法提取到想要的信息,原因在于这些网站都属于动态加载的网站,而豆瓣电影网站属于静态网页,在后文中将对这些技术进行进一步的讲解U N - + y _ 0 G。前文涉及的基础知识可参考下面链接:

爬虫所要了解的基础知识,这一篇就够了!Python网络爬虫实战系列

一文带你深入了解并学会Python爬虫库!从此数据不用愁

上一篇

短视频能为教育行业创造什么价值?

下一篇

凯恩遭多支豪门争抢?列维:拿2亿放人

你也可能喜欢

  • 暂无相关文章!

发表评论

您的电子邮件地址不会被公开。 必填项已用 * 标注

提示:点击验证后方可评论!

插入图片
返回顶部