前面所讲的都是对静态网页进行抓取,本博客介绍动态网站的抓取。 动态网站的抓取 相比静态网页来说困难一些,主要涉及的技术是Ajax和动态Html。简单的网页访问是无法获取完整的数据,需要对数据加载流程进行分析。针对不同的动态网页爬取方法,将分别用具体实例进行介绍。本博客主要是直接利用Ajax来获取数据。
页面分析
本博客以MTime电影网为例,主要爬取电影的评分票房等信息。首先使用火狐浏览器的控制台来查看页面信息。
对于页面中的票房信息是无法在HTML中获取到,其是通过js进行动态加载获得的,那么就查找相应的js响应。就是从一堆js请求中查看一些含有Ajax字段的请求。http://service.library.mtime.com/Movie.api?Ajax_CallBack=true&Ajax_CallBackType=Mtime.Library.Services&Ajax_CallBackMethod=GetMovieOverviewRating&Ajax_CrossDomain=1&Ajax_RequestUrl=http%3A%2F%2Fmovie.mtime.com%2F242129%2F&t=2020512134567406&Ajax_CallBackArgument0=242129
点进去之后查看返回的数据:
找到相应的链接和返回数据之后,就需要分析这个链接的构造方法和分析返回的数据。
(1)在链接中一共有7个参数,我们首先需要分析那些参数是不变的哪些是更具不同电影变化的。通过对比两个不同的电影链接可以发现其中有4个参数不变,有3个参数是动态变化的,分别是Ajax_RequestRrl、t和Ajax_CallBackArgument0。通过分析可以发现这三个参数分别表示的是当前页面url、当前请求时间和电影表示的数字。
(2)提取响应数据。响应内容主要分为三种,分别是正在上映的电影信息,一种即将上映的电影信息,最后一种是还有比较长时间才能上映的电影信息。具体的在代码中展示。
具体实现代码
本文代码是基于博客实现的,本博客只是将其中需要更改的部分修改了。
网页解析
在HtmlParser类中定义一个parser_url方法,代码如下:
def parser_url(self, page_url, response):
pattern = re.compile(r'(http://movie.mtime.com/(\d+)/)')
urls = pattern.findall(response)
if urls != None:
return list(set(urls))
else:
return None
提取响应数据中的有效数据:
def parser_json(self, page_url, respone):
"""
解析响应
:param page_url:
:param respone:
:return:
"""
#将“=”和“;”之间的内容提取出来
pattern = re.compile(r'=(.*?);')
result = pattern.findall(respone)[0]
if result != None:
value = json.loads(result)
try:
isRelease = value.get('value').get('isRelease')
except Exception,e:
print(e)
return None
if isRelease:
if value.get('value').get('hotValue') == None:
return self._parser_release(page_url, value)
else:
self._parser_no_release(page_url, value, isRelease = 2)
else:
return self._parser_no_release(page_url, value)
def _parser_release(self, page_url, value):
"""
解析已上映的影片
:param page_url:
:param value:
:return:
"""
try:
isRelease = 1
movieRating = value.get('value').get('movieRating')
boxOffice = value.get('value').get('boxOffice')
movieTitle = value.get('value').get('movieTitle')
RPictureFinal = movieRating.get('RPictureFinal')
RStoryFinal = movieRating.get('RStoryFinal')
RDirectorFinal = movieRating.get('RDirectorFinal')
ROtherFinal = movieRating.get('ROtherFinal')
RatingFinal = movieRating.get('RatingFinal')
MovieId = movieRating.get('MovieId')
Usercount = movieRating.get('Usercount')
AttitudeCount = movieRating.get('AttitudeCount')
TotalBoxOffice = boxOffice.get('TotalBoxOffice')
TotalBoxOfficeUnit = boxOffice.get('TotalBoxOfficeUnit')
TodayBoxOffice = boxOffice.get('TodayBoxOffice')
TodayBoxOfficeUnit = boxOffice.get('TodayBoxOfficeUnit')
showDays = boxOffice.get('ShowDays')
try:
Rank = boxOffice.get('Rank')
except Exception,e:
Rank = 0
return (MovieId,movieTitle,RatingFinal,
ROtherFinal,RPictureFinal,RDirectorFinal,
RStoryFinal,Usercount,AttitudeCount,
TotalBoxOffice+TotalBoxOfficeUnit,
TodayBoxOffice+TodayBoxOfficeUnit,
Rank,showDays,isRelease)
except Exception,e:
print(e,page_url,value)
return None
def _parser_no_release(self,page_url,value,isRelease = 0):
try:
movieRating = value.get('value').get('movieRating')
movieTitle = value.get('value').get('movieTitle')
RPictureFinal = movieRating.get('RPictureFinal')
RStoryFinal = movieRating.get('RStoryFinal')
RDirectorFinal = movieRating.get('RDirectorFinal')
ROtherFinal = movieRating.get('ROtherFinal')
RatingFinal = movieRating.get('RatingFinal')
MovieId = movieRating.get('MovieId')
Usercount = movieRating.get('Usercount')
AttitudeCount = movieRating.get('AttitudeCount')
try:
Rank = value.get('value').get('hotValue').get('Ranking')
except Exception,e:
Rank = 0
return (MovieId,movieTitle,RatingFinal,
ROtherFinal,RPictureFinal,RDirectorFinal,
RStoryFinal,Usercount,AttitudeCount,u'无',
u'无',Rank,0,isRelease)
except Exception,e:
print(e, page_url, value)
return None
爬虫调度器
def dynamic_crawl(self, root_url):
content = self.downloader.download(root_url)
urls = self.parser.parser_url(root_url,content)
for url in urls:
try:
t = time.strftime("%Y%m%d%H%M%S3282", time.localtime())
rank_url ='http://service.library.mtime.com/Movie.api'\
'?Ajax_CallBack=true'\
'&Ajax_CallBackType=Mtime.Library.Services'\
'&Ajax_CallBackMethod=GetMovieOverviewRating'\
'&Ajax_CrossDomain=1'\
'&Ajax_RequestRrl=%s'\
'&t=%s'\
'&Ajax_CallBackArgument0=%s'%(url[0],t,url[1])
rank_content = self.downloader.download(rank_url)
data = self.parser.parser_json(rank_url,rank_content)
print(data)
except Exception,e:
print('Crawl failed')
if __name__=="__main__":
spider_main = SpiderMain()
spider_main.dynamic_crawl("http://theater.mtime.com/China_Beijing/")