爬⾍demo——爬取电影天堂的资源,存储到本地json⽂件
电影天堂⾥⾯的数据还是⾮常丰富的,这次的爬⾍demo,是对电影天堂中的电影数据进⾏爬取,包括电影⽚名,导演,主演,演员等信息以及最后的迅雷下载地址。
经过4000部电影的爬取测试,我对代码多次进⾏优化,⽬前为⽌已没有什么bug,⾄少可以顺利对⽹站中的电影进⾏爬取。
⼀、基本介绍
⽂章的最后,我会给出爬⾍的完成代码,⽂章中的代码⽚段如果看上去⽐较乱的话,可以在了解爬⾍步骤和思想之后,通过完成代码来梳理⾃⼰的思路。
本次爬⾍使⽤到三个库,⽤于请求⽹页内容的requests库,⽤于对⽹页内容数据进⾏过滤处理的lxml库,已经⽤于json格式转换的json库。
所以在使⽤之前要引⼊这些库,并且保证⾃⼰项⽬中包含这些库,如果没有,⾃⾏进⾏安装。
import requests
from lxml import etree
import json
⼆、分析电影的链接,为爬⾍做准备
⾸先对电影天堂进⾏分析,我注意到⽹站⾸页有【2018新⽚精品】这⼀个版块,点击右边的更多按钮,可以来到电影的列表页。
通过对这些列表页的分析,我发现这不仅仅是2018的最新电影,⼀共有179页,共4473条数据。仔细分析之后,发现最早的影⽚是
2009年的。觉得数量还是⽐较多,所以当时就决定对和4000多部电影进⾏爬取。
分析这些列表的URL,不难发现其中的规律,列表的URL如下:
······
于是我写了下⾯代码,⼀次性⽣成全部的电影列表页(第1页~第179页)的URL,并存储到列表中:
def movie_list_page():
base_url ="www.dytt8/html/gndy/dyzz/list_23_{}.html"
page_urls =[]有个叫什么代码的电影
for x in range(1,180):
page_urls.append(base_url.format(x))
return page_urls
明确这⼀点,下⾯我们要开始爬取列表页中的内容。这⼀步是⾮常简单的,简单看⼀下页⾯就会知道,这些电影的详情页地址肯定是很规律的。⼤多数是ul标签下的li标签或者是table标签,于是我写了下⾯这些代码,获取电影的详情页地址:
# 传⼊电影列表页地址,返回这⼀页中每⼀部电影的详情页⾯链接
def get_detail_url(url):
BASE_DIMAIN ="www.dytt8"# 定义基础域名
response = (url, headers=HEADERS)
text =
html = etree.HTML(text)
detail_urls = html.xpath("//table[@class='tbspan']//a[@href!='/html/gndy/jddy/index.html']/@href")
detail_urls =map(lambda x: BASE_DIMAIN + x, detail_urls)
return detail_urls
三、请求电影的详情页⾯,过滤数据
现在我们拿到了所有的电影列表页地址,即从第1页到第179页的地址。在代码中使⽤循环语句,通过这些地址我们⼜能够获取每⼀页中所有电影的详情页⾯信息。这样⼀来我们就相当于成功⼀半,下⾯的⼯作就是请求电影详情页⾯中的数据,以及对这些数据进⾏过滤和处理。
⾸先我们使⽤requests库,将电影详情页⾯中的所有内容全部请求下来,然后获取存放电影信息的那块内容,缩⼩我们的数据范围,⽅便我们进⼀步过滤数据。代码如下:
movie ={}# ⽤作后⾯的存放电影的数据
HEADERS ={
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36"
}
detail_response = (url, headers=HEADERS)
detail_text = t.decode(encoding="gb18030", errors="ignore")# 注意这⾥设置的编码格式是根据电影天堂的编码格式来的,同时设置errors="ignore",忽略⼀些极其特殊的字符的解码错误
detail_html = etree.HTML(detail_text)
if len(detail_html.xpath("//div[@id='Zoom']"))>0:
zoom = detail_html.xpath("//div[@id='Zoom']")[0]
else:
return movie # 说明没有爬取成功,直接跳过返回⼀个空字典,放弃对这⼀步电影的爬取
由于电影天堂中,关于电影内容的部分的数据表⽰不够明显,⽐如没有特定的class和id来标识。所有我们需要通过xpath语法中的text()获取表⽰电影内容的⽂本信息列表,然后对这些列表进⾏遍历,过滤我们需要的信息,具体代码如下:
movie ={}# ⽤作后⾯的存放电影的数据
# text_list = zoom.xpath(".//p/text()|.//p/span/text()") # 版本1.0,没有考虑到有的页⾯中会多出span标签
# text_list = zoom.xpath(".//p/span/text()|.//p/text()") # 版本2.0,没有考虑到有的页⾯中会缺少标签
text_list = zoom.xpath(".//text()")# 版本3.0,直接获取页⾯中的⽂本,进⾏过滤
for(index, text)in enumerate(text_list):
# print(text)
if text.startswith("◎译 名"):
movie["teanslation_title"]= place("◎译 名","").strip()
elif text.startswith("◎⽚ 名"):
movie["real_title"]= place("◎⽚ 名","").strip()
elif text.startswith("◎年 代"):
movie["time"]= place("◎年 代","").strip()
elif text.startswith("◎产 地"):
movie["place"]= place("◎产 地","").strip()
elif text.startswith("◎类 别"):
movie["category"]= place("◎类 别","").strip()
elif text.startswith("◎语 ⾔"):
movie["language"]= place("◎语 ⾔","").strip()
elif text.startswith("◎上映⽇期"):
movie["release_time"]= place("◎上映⽇期","").strip()
elif text.startswith("◎⾖瓣评分"):
movie["douban_score"]= place("◎⾖瓣评分","").strip()
elif text.startswith("◎⽚ 长"):
movie["length"]= place("◎⽚ 长","").strip()
elif text.startswith("◎导 演"):
movie["director"]= place("◎导 演","").strip()
elif text.startswith("◎主 演"):
actors =[]
actors.place("◎主 演","").strip())
for num in range(index +1, index +10):
if(text_list[num].startswith("◎简 介")):
break
else:
actors.append(text_list[num].strip())
movie["actors"]= actors
elif text.startswith("◎简 介"):
conttent_index = index +1
movie["introduction"]= text_list[conttent_index].strip()
# 由于页⾯的原因,对下载链接进⾏特殊过滤
if len(zoom.xpath(".//td/a/@href"))>0:
download_url = zoom.xpath(".//td/a/@href")[0]
elif len( zoom.xpath(".//td//a/@href"))>0:
download_url = zoom.xpath(".//td//a/@href")[-1]
else:
download_url ="爬取失败,⼿动修改迅雷下载链接!"
movie["download_url"]= download_url
print("·", end=" ")# 简单的标识,在爬取的时候,成功爬取⼀部电影,就会打印出⼀个“·”
return movie
四、将数据处理成json格式,保存到本地json⽂件中
完成上述任务,我们的爬⾍也基本上已经接近尾声。下⾯要做的就是,调⽤封装上述代码的函数,将数据处理成json格式,然后以每⼀列表为单位,存储到本地json⽂件中。
page_num =1
page_urls = movie_list_page()
# 以每⼀列表页为单位,完成每⼀列表页中电影的爬取,处理成json,写⼊到本地⽂件中
for(index, page_url)in enumerate(page_urls):
file_name ="new_movie_"+str(index + page_num)+".json"# 设置存放每⼀页电影信息的json⽂件的名称 one_page_movie_content =[]# 每⼀页中所有电影的信息
movie_detail_urls = get_detail_url(page_url)
for movie_detail_url in movie_detail_urls:
movie_content = get_movie_content(movie_detail_url)
one_page_movie_content.append(movie_content)
# 将爬取的每⼀页的电影数据,分别写⼊到⼀个json⽂件中
one_page_movie_content_str = json.dumps(one_page_movie_content, ensure_ascii=False, indent=2)
with open(file_name,"w", encoding="utf-8")as f:
f.write(one_page_movie_content_str)
print("第"+str(index + page_num)+"页电影爬取完成,写⼊到"+ file_name +"⽂件中")
四、爬⾍完成代码下载:
CSDN下载地址:
百度云下载地址:
Github下载地址:以后整合⾃⼰的全部爬⾍demo,再⼀并上传,给出地址
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论