爬取电影天堂的最新电影是什么(电影下载爬虫
点击上方蓝字关注公众号
码个蛋第262次推文
以后再也不愁看什么电影了
作者:猴哥Yuri
博客:
https://www.jianshu.com/u/f46becd1ed83文章目录
爬取目标
设计爬虫程序
确定爬普罗米修斯 电影取入口
爬取思路
设计爬虫架构
代码实现
爬取结果
前面两篇文章介绍 requests 和 xpath 的用法。我们推崇学以致用,所以本文讲解利用这两个工具进行实战。
0
爬取目标
本次爬取的站点选择电影天堂,网址是普罗米修斯 电影: www.dytt8.net。爬取内容是整个站点的所有电影信息,包括电影名称,导演、主演、下载地址等。具体抓取信息如下图所示:
1
设计爬虫程序
2.1 确定爬取入口
电影天堂里面的电影数目成千上万,电影类普罗米修斯 电影型也是让人眼花缭乱。我们为了保证爬取的电影信息不重复, 所以要确定一个爬取方向。目前这情况真让人无从下手。但是,我们点击主页中的【最新电影】选项,跳进一个新的页面。蓦然有种柳暗花明又一村的感觉。
由图可普罗米修斯 电影知道,电影天堂有 5 个电影栏目,分别为最新电影、日韩电影、欧美电影、国内电影、综合电影。每个栏目又有一定数量的分页,每个分页有 25 条电影信息。那么程序的入口可以有 5 个 url 地址。这 5 普罗米修斯 电影个地址分别对应每个栏目的首页链接。
2.2 爬取思路
知道爬取入口,后面的工作就容易多了。我通过测试发现这几个栏目除了页面的 url 地址不一样之外,其他例如提取信息的 xpath 路径是一样的。因此,我普罗米修斯 电影把 5 个栏目当做 1 个类,再该类进行遍历爬取。
我这里“最新电影”为例说明爬取思路。
1)请求栏目的首页来获取到分页的总数,以及推测出每个分页的 url 地址;
2)将获取到的分页 url 存放到名为 普罗米修斯 电影floorQueue 队列中;
3)从 floorQueue 中依次取出分页 url,然后利用多线程发起请求;
4)将获取到的电影页面 url 存入到名为 middleQueue 的队列;
5)从 midd普罗米修斯 电影leQueue 中依次取出电影页面 url,再利用多线程发起请求;
6)将请求结果使用 Xpath 解析并提取所需的电影信息;
7)将爬取到的电影信息存到名为 contentQueue 队列中;
8)从 c普罗米修斯 电影ontentQueue 队列中依次取出电影信息,然后存到数据库中。
2.3 设计爬虫架构
根据爬取思路,我设计出爬虫架构。如下图所示:
2.4 代码实现
主要阐述几个重要的类的代码
main 类
主要工作两个:第普罗米修斯 电影一,实例化出一个dytt8Moive对象,然后开始爬取信息。第二,等爬取结束,将数据插入到数据库中。
处理爬虫的逻辑代码如下:
# 截止到2017-08-08, 最新电影一共才有 164个页面
LASTEST普罗米修斯 电影_MOIVE_TOTAL_SUM =6 #164# 请求网络线程总数, 线程不要调太好, 不然会返回很多 400THREAD_SUM = 5def startSpider:
# 实例化对象
# 获取【最新电影】普罗米修斯 电影有多少个页面
LASTEST_MOIVE_TOTAL_SUM = dytt_Lastest.getMaxsize
print(【最新电影】一共 + str(LASTEST_MOIVE_TOTAL_SUM) 普罗米修斯 电影+ 有个页面)
dyttlastest = dytt_Lastest(LASTEST_MOIVE_TOTAL_SUM)
floorlist = dyttlastest.getPageUrlList
floor普罗米修斯 电影Queue = TaskQueue.getFloorQueue
for item in floorlist:
floorQueue.put(item, 3)
# print(floorQueue.qsize)
f普罗米修斯 电影or i in range(THREAD_SUM):
workthread = FloorWorkThread(floorQueue, i)
workthread.start
while True:
ifTask普罗米修斯 电影Queue.isFloorQueueEmpty:
break
else:
pass
for i in range(THREAD_SUM):
workthread = TopWorkThread(TaskQueue普罗米修斯 电影.getMiddleQueue, i)
workthread.start
while True:
ifTaskQueue.isMiddleQueueEmpty:
break
else:
pass
insertDat普罗米修斯 电影a
if __name__ == __main__:
startSpider创建数据库以及表,接着再把电影信息插入到数据库的代码如下:
def insertData:
DBName = dytt.db
db = 普罗米修斯 电影sqlite3.connect(./ + DBName, 10)
conn = db.cursor
SelectSql = Select * from sqlite_master where type = "table"普罗米修斯 电影 and name="lastest_moive";
CreateTableSql =
Create Tablelastest_moive (
m_id INTEGER PRIMARY KEY,
m_type varcha普罗米修斯 电影r(100),
m_trans_name varchar(200),
m_name varchar(100),
m_decade varchar(30),
m_conutry varchar(30),
m_level v普罗米修斯 电影archar(100),
m_language varchar(30),
m_subtitles varchar(100),
m_publish varchar(30),
m_IMDB_socre varchar(5普罗米修斯 电影0),
m_douban_score varchar(50),
m_format varchar(20),
m_resolution varchar(20),
m_size varchar(10),
m_duratio普罗米修斯 电影n varchar(10),
m_director varchar(50),
m_actors varchar(1000),
m_placard varchar(200),
m_screenshot varchar(2普罗米修斯 电影00),
m_ftpurl varchar(200),
m_dytt8_url varchar(200)
);
InsertSql =
Insert intolastest_moive(m_type, m_trans普罗米修斯 电影_name, m_name, m_decade, m_conutry, m_level, m_language, m_subtitles, m_publish, m_IMDB_socre,
m_doub普罗米修斯 电影an_score, m_format, m_resolution, m_size, m_duration, m_director, m_actors, m_placard, m_screenshot,普罗米修斯 电影 m_ftpurl,
m_dytt8_url)
values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
if not c普罗米修斯 电影onn.execute(SelectSql).fetchone:
conn.execute(CreateTableSql)
db.commit
print(==== 创建表成功 ====)
else:
prin普罗米修斯 电影t(==== 创建表失败, 表已经存在 ====)
count = 1while notTaskQueue.isContentQueueEmpty:
item = TaskQueue.getContentQue普罗米修斯 电影ue.get
conn.execute(InsertSql, Utils.dirToList(item))
db.commit
print(插入第 + str(count) + 条数据成功)
count = count普罗米修斯 电影 + 1db.commit
db.close
TaskQueue 类
维护 floorQueue、middleQueue、contentQueue 三个队列的管理类。之所以选择队列的数据结构,是因为爬虫程序需要普罗米修斯 电影用到多线程,队列能够保证线程安全。
dytt8Moive 类
dytt8Moive 类是本程序的主心骨。程序最初的爬取目标是 5 个电影栏目,但是目前只现实了爬取最新栏目。如果你想爬取全部栏目电影,只需对普罗米修斯 电影 dytt8Moive 稍微改造下即可。
class dytt_Lastest(object):
# 获取爬虫程序抓取入口
breakoutUrl = http://www.dytt8.net/html/gn普罗米修斯 电影dy/dyzz/index.htmldef __init__(self, sum):
self.sum = sum
# 获取【最新电影】有多少个页面
# 截止到2017-08-08, 最新电影一共才有 164普罗米修斯 电影个页面
@classmethod
def getMaxsize(cls):
response = requests.get(cls.breakoutUrl, headers=RequestModel.get普罗米修斯 电影Headers, proxies=RequestModel.getProxies, timeout=3)
# 需将电影天堂的页面的编码改为 GBK, 不然会出现乱码的情况
response.encodin普罗米修斯 电影g =GBKselector = etree.HTML(response.text)
# 提取信息
optionList = selector.xpath("//select[@name=sldd]/te普罗米修斯 电影xt")
return len(optionList) - 1 # 因首页重复, 所以要减1def getPageUrlList(self):
主要功能:目录页url取出,比如:http://www.dytt8普罗米修斯 电影.net/html/gndy/dyzz/list_23_+ str(i) + .htmltemplist =
request_url_prefix = http://www.dytt8.net/html/g普罗米修斯 电影ndy/dyzz/templist = [request_url_prefix + index.html]
for i in range(2, self.sum + 1):
templist.append(req普罗米修斯 电影uest_url_prefix +list_23_ + str(i) + .html)
fort in templist:
print(request url is ### + t + ###)
returntem普罗米修斯 电影plist
@classmethod
def getMoivePageUrlList(cls, html):
获取电影信息的网页链接selector = etree.HTML(html)
templist =普罗米修斯 电影 selector.xpath("//div[@class=co_content8]/ul/td/table/tr/td/b/a/@href")
# print(len(templist))
# print(普罗米修斯 电影templist)
returntemplist
@classmethod
def getMoiveInforms(cls, url, html):
解析电影信息页面的内容, 具体如下:类型 : 疾速特攻/疾普罗米修斯 电影速追杀2][BD-mkv.720p.中英双字][2017年高分惊悚动作]◎译名 : ◎译\u3000\u3000名\u3000疾速特攻/杀神John Wick 2(港)/捍卫任务2(台)/疾速追杀2/普罗米修斯 电影极速追杀:第二章/约翰·威克2◎片名 : ◎片\u3000\u3000名\u3000John Wick: Chapter Two◎年代 : ◎年\u3000\u3000代\u30002017◎国家 :普罗米修斯 电影 ◎产\u3000\u3000地\u3000美国◎类别 : ◎类\u3000\u3000别\u3000动作/犯罪/惊悚◎语言 : ◎语\u3000\u3000言\u3000英语◎字幕 : ◎字\u30普罗米修斯 电影00\u3000幕\u3000中英双字幕◎上映日期 :◎上映日期\u30002017-02-10(美国)◎IMDb评分 : ◎IMDb评分\xa0 8.1/10 from 86,240 users◎豆普罗米修斯 电影瓣评分 : ◎豆瓣评分\u30007.7/10 from 2,915 users◎文件格式 : ◎文件格式\u3000x264 + aac◎视频尺寸 : ◎视频尺寸\u30001280 x 720◎文普罗米修斯 电影件大小 : ◎文件大小\u30001CD◎片长 : ◎片\u3000\u3000长\u3000122分钟◎导演 : ◎导\u3000\u3000演\u3000查德·史塔赫斯基 Chad Stahels普罗米修斯 电影ki◎主演 :◎简介 : 暂不要该字段◎获奖情况 : 暂不要该字段◎海报影片截图下载地址# print(html)
contentDir = {
type: ,
trans_name: ,
name: ,
dec普罗米修斯 电影ade: ,
conutry: ,
level: ,
language: ,
subtitles: ,
publish: ,
IMDB_socre: ,
douban_score: ,
format: ,
resolu普罗米修斯 电影tion: ,
size: ,
duration: ,
director: ,
actors: ,
placard: ,
screenshot: ,
ftpurl: ,
dytt8_url:
}
selector = e普罗米修斯 电影tree.HTML(html)
content = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/td/p/text")
# 匹配出来有两张普罗米修斯 电影图片, 第一张是海报, 第二张是电影画面截图
imgs = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/td/p/img/@src")
#普罗米修斯 电影print(content)
# 为了兼容 2012年前的页面
if not len(content):
content = selector.xpath("//div[@class=co_content8]/u普罗米修斯 电影l/tr/td/div/div/td/span/text")
# 有些页面特殊, 需要用以下表达式来重新获取信息
# 电影天堂页面好混乱啊~
if not len(content):
content = sele普罗米修斯 电影ctor.xpath("//div[@class=co_content8]/ul/tr/td/div/td/div/text")
if not len(content):
content = selector普罗米修斯 电影.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/p/font/text")
if len(content) < 5:
content = selec普罗米修斯 电影tor.xpath("//div[@class=co_content8]/ul/tr/td/p/font/text")
if not len(content):
content = selector.xpat普罗米修斯 电影h("//div[@class=co_content8]/ul/tr/td/div/div/td/p/span/text")
if not len(content):
content = selector.x普罗米修斯 电影path("//div[@class=co_content8]/ul/tr/td/div/div/td/div/span/text")
if not len(content):
content = selec普罗米修斯 电影tor.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/font/text")
if not len(content):
content = sele普罗米修斯 电影ctor.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/p/text")
# print(content)
# 不同渲染页面要采取不同的抓取方式抓普罗米修斯 电影取图片
if not len(imgs):
imgs = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/img/@src")
ifn普罗米修斯 电影otlen(imgs):
imgs = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/p/img/@src")
if not le普罗米修斯 电影n(imgs):
imgs = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/div/img/@src")
if not len(普罗米修斯 电影imgs):
imgs = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/td/div/img/@src")
# 类型
if content[0普罗米修斯 电影][0:1] != ◎:
contentDir[type] = [ + content[0]
actor =
foreach in content:
if each[0:5] == ◎译\u3000\u3000名:
# 普罗米修斯 电影译名 ◎译\u3000\u3000名\u3000 一共占居6位
contentDir[trans_name] = each[6: len(each)]
elif each[0:5] == ◎片\u3000\u普罗米修斯 电影3000名:
# 片名
contentDir[name] = each[6: len(each)]
elif each[0:5] == ◎年\u3000\u3000代:
# 年份
contentDir[decade普罗米修斯 电影] = each[6: len(each)]
elif each[0:5] == ◎产\u3000\u3000地:
# 产地
contentDir[conutry] = each[6: len(each)]
eli普罗米修斯 电影f each[0:5] == ◎类\u3000\u3000别:
# 类别
contentDir[level] = each[6: len(each)]
elif each[0:5] == ◎语\u3000\u30普罗米修斯 电影00言:
# 语言
contentDir[language] = each[6: len(each)]
elif each[0:5] == ◎字\u3000\u3000幕:
# 字幕
contentDir[subt普罗米修斯 电影itles] = each[6: len(each)]
elif each[0:5] == ◎上映日期:
# 上映日期
contentDir[publish] = each[6: len(each)]
elif e普罗米修斯 电影ach[0:7] == ◎IMDb评分:
# IMDb评分
contentDir[IMDB_socre] = each[9: len(each)]
elif each[0:5] == ◎豆瓣评分:
# 豆瓣评分
co普罗米修斯 电影ntentDir[douban_score] = each[6: len(each)]
elif each[0:5] == ◎文件格式:
# 文件格式
contentDir[format] = each[6: l普罗米修斯 电影en(each)]
elif each[0:5] == ◎视频尺寸:
# 视频尺寸
contentDir[resolution] = each[6: len(each)]
elif each[0:5] == ◎文件普罗米修斯 电影大小:
# 文件大小
contentDir[size] = each[6: len(each)]
elif each[0:5] == ◎片\u3000\u3000长:
# 片长
contentDir[duratio普罗米修斯 电影n] = each[6: len(each)]
elif each[0:5] == ◎导\u3000\u3000演:
# 导演
contentDir[director] = each[6: len(each)]
e普罗米修斯 电影lif each[0:5] == ◎主\u3000\u3000演:
# 主演
actor = each[6: len(each)]
foritem in content:
if item[0: 4] == \u3000普罗米修斯 电影\u3000\u3000\u3000:
actor = actor + \n + item[6: len(item)]
# 主演
contentDir[actors] = actor
# 海报
if imgs[0] !普罗米修斯 电影= None:
contentDir[placard] = imgs[0]
# 影片截图
if imgs[1] != None:
contentDir[screenshot] = imgs[1]
ftp = se普罗米修斯 电影lector.xpath("//div[@class=co_content8]/ul/tr/td/div/td/table/tbody/tr/td/a/text")
# 为了兼容 2012年前的页面
ifn普罗米修斯 电影otlen(ftp):
ftp = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/table/tbody/tr/td/fon普罗米修斯 电影t/a/text")
if not len(ftp):
ftp = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/table/tb普罗米修斯 电影ody/tr/td/a/text")
if not len(ftp):
ftp = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/普罗米修斯 电影div/table/tbody/tr/td/font/a/text")
if not len(ftp):
ftp = selector.xpath("//div[@class=co_content8]/ul/普罗米修斯 电影tr/td/div/td/div/table/tbody/tr/td/a/text")
if not len(ftp):
ftp = selector.xpath("//div[@class=co_conte普罗米修斯 电影nt8]/ul/tr/td/div/td/table/tbody/tr/td/a/text")
if not len(ftp):
ftp = selector.xpath("//div[@class=co_c普罗米修斯 电影ontent8]/ul/tr/td/div/div/td/p/span/a/text")
if not len(ftp):
ftp = selector.xpath("//div[@class=co_cont普罗米修斯 电影ent8]/ul/tr/td/div/div/td/div/div/table/tbody/tr/td/font/a/text")
if not len(ftp):
ftp = selector.xpath(普罗米修斯 电影"//div[@class=co_content8]/ul/tr/td/div/div/td/span/table/tbody/tr/td/font/a/text")
if not len(ftp):
ftp普罗米修斯 电影 = selector.xpath("//div[@class=co_content8]/ul/tr/td/div/div/td/div/span/div/table/tbody/tr/td/font普罗米修斯 电影/a/text")
contentDir[ftpurl] = ftp[0]
# 页面链接
contentDir[dytt8_url] = url
print(contentDir)
returncontentD普罗米修斯 电影ir选择字典类型作为存储电影信息的数据结构,也是自己爬坑之后才决定的。这算是该站点另一个坑人的地方。电影详情页中有些内容节点是没有,例如类型、豆瓣评分,所以无法使用列表按顺序保存。
2
爬取结果
我这里展示普罗米修斯 电影自己爬取最新栏目中 4000 多条数据中前面部分数据。
附:源代码地址(https://link.jianshu.com/?t=
https://github.com/monkey-soft/Moives普罗米修斯 电影Spider)