没有全部完成,没有过程解释,只有整体框架,等我写完,下周末继续完成。
如题,我要爬取豆瓣电影Top250的相关信息,包括但不限于——电影排名、电影名、电影导演、主演、编剧、类型、制片国家、语言、 上映时间、片长、别名、评分、评分人数、5星占比等。
希望用到的技能:
- 爬虫基础知识
- BeautifulSoup的使用
- 多进程
- 操作数据库
- 使用队列
- 文件操作
- MATLAB画图统计,实现数据可视化
- 下载图片
- 正则表达式
- 使用代理池、防止封锁
- 克服反爬机制等
我分析过了整个网站,大致分为以下几个步骤进行:
- 先获取250个电影的详情页的地址,保存为txt文件,并将其保存到队列中等待处理
- 从队头开始爬取页面,保存为BeautifulSoup对象,同时队首出队。这里可能会遇到反爬机制
- 处理BeautifulSoup对象,清洗数据,获得电影相关信息,以及其电影海报页面地址,其中会用到正则表达式,这里也可能会遇到反爬机制
- 将清洗后的数据存入数据库
- 下载相关电影海报图,并附上相关信息,将其存到一个文件夹下txt+pic
- 利用MATLAB处理数据,输出统计图
2、3、5尝试使用多进程加快处理速度
目前已经完成的步骤:1、2、5
正在进行的步骤:3
遇到的问题:多进程在win10上遇到了神奇的bug,还没解决、在清洗数据时遇到了一点小问题,是对BeautifulSoup掌握度不够的问题、基础不扎实。
在写的时候我就注意了爬虫的礼仪,设定了访问间隔时间,并没有遇到封锁,很幸运。可以说豆瓣简直就是爬虫新手的乐园,难度不大、但有一定挑战性。
通过这次练习,我对自己的水平有了大致的了解,远远不够——MATLAB不会使、代理IP不熟悉、多进程不会用、相关基础知识不深刻、数据结构使用不合理、代码结构不规范等很多问题。
在写代码时,发现了很多问题,这都将是我接下来努力的方向!!
目标
代码没写完,主程序没写,下周末更新!
全部代码:
import time
import os
from bs4 import BeautifulSoup
from urllib.request import urlopen
from urllib.request import urlretrieve
#我用的自己写的队列,模块QUEUE使用不熟练
class LNode:
def __init__(self,arg):
self.data=arg
self.next=None
class MyQueue:
#模拟队列
def __init__(self):
#phead=LNode(None)
self.data=None
self.next=None
self.front=self#指向队列首
self.rear=self#指向队列尾
#判断队列是否为空,如果为空返回True,否则返回false
def isEmpty(self):
return self.front==self.rear
#返回队列的大小
def size(self):
p=self.front
size=0
while p.next!=self.rear.next:
p=p.next
size+=1
return size
#返回队列首元素
def top(self):
if not self.isEmpty():
return self.front.next.data
else:
print("队列为空")
return None
#返回队列尾元素
def bottom(self):
if not self.isEmpty():
return self.rear.data
else:
print("队列为空")
return None
#出队列
def pop(self):
if self.size()==1:
data=self.front.next
self.rear=self
return data.data
elif not self.isEmpty():
data=self.front.next
self.front.next=self.front.next.next
print("出队列成功")
return data.data
else:
print("队列已为空")
return None
#入队列
def push(self,item):
tmp=LNode(item)
self.rear.next=tmp
self.rear=self.rear.next
print("入队列成功")
#清空队列
def destroy(self):
self.next=None
print("队列已清空")
#打印队列
def showQueue(self):
if not self.isEmpty():
p=self.front.next
while p != self.rear.next:
print(p.data)
p=p.next
#获得10页包含250个简介的页面地址
def get_ten_pageurl():
array=[]
for i in range(0,250,25):
array.append("https://movie.douban.com/top250?start="+str(i)+"&filter=")
return array
# 得到每一个电影的详情页地址
def get_250movie_page_url(ten_pageurl,Directory):
"""
输入10页地址
将top250 的电影首页地址保存下来,同时存到队列中和本地text
"""
if not os.path.exists(Directory):
os.makedirs(Directory)
url_queue=MyQueue()
for page_url in ten_pageurl:
try:
html = urlopen(page_url)
bsobj = BeautifulSoup(html, features="html.parser")
# 得到当前页面上25个包含序号、详情页的地址的div标签,存为列表
movie_info_items = bsobj.findAll("div", {"class": "pic"})
for movie_info in movie_info_items:
try:
movie_id = int(movie_info.find("em").get_text())
movie_info_url = movie_info.find("a").attrs["href"]
movie_name=movie_info.find("img").attrs["alt"]
url_queue.push(movie_info_url)
with open(Directory + "/250homepage_url.txt", "a") as f:
f.write(str(movie_id))
f.write("\t")
f.write(movie_name)
f.write("\t")
f.write(movie_info_url)
f.write("\n")
print("获取movie_id/movie_info_url成功:", movie_id)
except:
print("获取movie_id/movie_info_url失败:", movie_info[30:34])
continue
time.sleep(2)
except:
print("页面%s处理失败"%(page_url))
time.sleep(1)
continue
return url_queue
#获取详情页
def get_movie_info(url):
try:
html = urlopen(url)
bsobj = BeautifulSoup(html, features="html.parser")
time.sleep(2)
return bsobj
except:
print("页面%s处理失败"%(url[-8:]))
time.sleep(1)
return None
#处理详情页
def configure_infopage(bsobj):
try:
#电影排名:
movie_id=bsobj.find("span", {"class": "top250-no"}).get_text()
# 得到当前页面上的电影名称
movie_name = bsobj.find("span", {"property": "v:itemreviewed"}).get_text()
#电影简介
movie_intro=bsobj.find("span",{"property":"v:summary"})
#获取电影海报页面链接
movie_photos=bsobj.find("a",{"class":"nbgnbg"}).attrs["href"]
#电影详细信息左
movie_info_items=bsobj.find("div",{"class":"subjectwrap clearfix"})
#处理电影详细信息
#导演: 弗兰克·德拉邦特
movie_directer=movie_info_items.find("a",{"rel":"v:directedBy"}).get_text()
#编剧: 弗兰克·德拉邦特 / 斯蒂芬·金
movie_attrs=None
#主演: 蒂姆·罗宾斯 / 摩根·弗里曼 / 鲍勃·冈顿 / 威廉姆·赛德勒 / 克兰西·布朗 / 吉尔·贝罗斯 / 马克·罗斯顿 / 詹姆斯·惠特摩 / 杰弗里·德曼 / 拉里·布兰登伯格 / 尼尔·吉恩托利 / 布赖恩·利比 / 大卫·普罗瓦尔 / 约瑟夫·劳格诺 / 祖德·塞克利拉 / 保罗·麦克兰尼 / 芮妮·布莱恩 / 阿方索·弗里曼 / V·J·福斯特 / 弗兰克·梅德拉诺 / 马克·迈尔斯 / 尼尔·萨默斯 / 耐德·巴拉米 / 布赖恩·戴拉特 / 唐·麦克马纳斯
movie_actors=None
#类型: 剧情 / 犯罪
movie_genre=None
#制片国家/地区: 美国
movie_saition=movie_info_items.find("a",{"rel":"v:directedBy"}).get_text()
#语言: 英语
movie_language=None
#上映日期: 1994-09-10(多伦多电影节) / 1994-10-14(美国)
movie_initialReleaseDate=None
#片长: 142分钟
movie_Runtime=None
#又名: 月黑高飞(港) / 刺激1995(台) / 地狱诺言 / 铁窗岁月 / 消香克的救赎
movie_alias=None
#IMDb链接: tt0111161
movie_IMDb_url=None
#电影评分信息
movie_votes_info=bsobj.find("div",{"id":"interest_sectl"})
#处理电影评分信息
#评分
movie_vote=None
#评分人数
movie_voters=None
#5星数量
movie_vote_5_stars=None
except:
print("电影信息处理失败")
return None
return [movie_id,movie_name,movie_vote,movie_voters,movie_vote_5_stars,movie_directer,movie_attrs,movie_actors,movie_genre,movie_saition,movie_language,\
movie_initialReleaseDate,movie_Runtime,movie_alias,movie_IMDb_url,movie_intro,movie_photos]
# 下载海报
def download_img(url,download_directory):
"""
保存海报
输入:下载文件地址,和板存路径
输出:将文件保存到相应文件下
"""
if not os.path.exists(download_directory):
os.makedirs(download_directory)
file_path=download_directory+url[-14:]
try:
urlretrieve(url, file_path)
print("1")
print("下载图片:%s完成!\n存储在:%s" % (url[-14:],file_path))
time.sleep(2)
except :
print("下载图片:%s失败!" % (url[-14:]))
return None
网友评论