写在系列之前:
多年前当我还是一个懵懂少年时,偶然间看到一本书:《大数据时代》,其中有一段介绍谷歌如何利用大数据预测流感的文字。当时我很震惊,这不就是神的能力吗?我要拥有该多好。清楚的记得当时的我立马打开电脑,搜索如何获取数据……于是后来走上修炼爬虫的这条不归路。
由于笔者是一位汽车工程师,工作中其实不太用得上爬虫,除非是写报告需要搜集大量数据的时候,才会码几段代码。爬虫只是我业余消磨时间一种爱好。但是用得少了,即使是以前精通的东西也会忘得一干二净。所以打算用一个系列来心路记录历程,以后忘记了也可以当做笔记来看。当然更重要的是“莺其鸣矣,寻其友声”。
今天我们就来讲讲如何爬虫猫眼的电影排行榜的电影名称、评分、演员和上映时间,并且下载电影高清海报。
在写爬虫之前,需要先观察一下网页:
1.在Chrome浏览器中,打开猫眼电影排行榜的网页以后,按一下F12,就可以看到下图左边的网页源码。
我发现在class属性为main的div标签里,有十对<dd>标签,一页正好是十个条目会不会我们要爬取的内容就在每一个<dd>标签里呢?
2.打开第一个<dd>标签,发现我们要爬取的内容都包含在里面。
3.处理分页
将页面拉到底部,会发现排行榜一共有十页,当然比较简单的方法是一页一页的爬取,但是我是不会放过任何一个能用递归的机会的。如何采用递归呢?下面是我的思路。
继续分析源码,发现class属性为“list-pager”的div标签里面有6队<li>标签,这些<li>与右边的分页一一对应,递归的方式如下:
a.建立空集合set()(具有去重功能)
b.找到初始初始页面的每个li标签下的每个a标签的href属性
c.将2中找到的href属性加上https://maoyan.com/board/4 后存储在set()中,并重复步骤2
d.递归停止的条件为set()中的元素个数达到最大分页数量,即10.
分析完网页,接下来正式开始码代码。
import re
from bs4 import BeautifulSoup
import requests
import operator
import csv
pages=set()
def getlinkset(wz):#用于获取所有分页的url
global pages
headers = {"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4) AppleWebKit/537.36(KTML,like Gecko) Chrome/52.0.2743.116 Safari/537.36"}
response=requests.get("https://maoyan.com/board/4"+wz,headers=headers)
bsobj=BeautifulSoup(response.text,"html5lib")
if len(pages)<=10:
links=bsobj.findAll("a",{"href":re.compile("^.?offset.*$")})
for link in links:
if link["href"] not in pages:
pages.add(link["href"])
wz=link["href"]
getlinkset(wz)
return pages
result_dict={}
picture_dict={}
def getcontent(suffix):#用于解析每个页面
global result_dict
global picture_dict
headers = {"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4) AppleWebKit/537.36(KTML,like Gecko) Chrome/52.0.2743.116 Safari/537.36"}
response=requests.get("https://maoyan.com/board/4"+suffix,headers=headers)
bsobj=BeautifulSoup(response.text,"html5lib")
for imagelink in bsobj.findAll("img",{"src":re.compile("^(http)?.*$")}):
picture_dict[imagelink["alt"]]=imagelink["src"].split("@")[0]
for nameflag in bsobj.findAll("div",{"class":"movie-item-info"}):
name=nameflag.find("p",{"class":"name"}).get_text()
star=nameflag.find("p",{"class":"star"}).get_text()
if "n" in star:
star=re.sub("n","",star)
star=re.sub(" *","",star)
releasetime = nameflag.find("p", {"class": "releasetime"}).get_text()
rated=nameflag.parent.find("i",{"class":"integer"}).get_text()+nameflag.parent.find("i",{"class":"fraction"}).get_text()
rank=int(nameflag.parent.parent.parent.find("i").get_text())
list=[name,rated,star,releasetime]
result_dict[rank]=",,,".join(list)
return result_dict
getlinkset("")
for link in pages:
getcontent(link)
filename = "F:python program filepictures"
result=sorted(result_dict.items(),key=operator.itemgetter(0),reverse=False)
# print(result)
resultfile=open(filename+r"result.csv","w+")
writer=csv.writer(resultfile,lineterminator='n')
writer.writerow(("排名","名称","评分","演员","上映时间"))
for i in result:
writer.writerow((i[0],i[1].split(",,,")[0],i[1].split(",,,")[1],i[1].split(",,,")[2],i[1].split(",,,")[3]))
resultfile.close()
for key,value in picture_dict.items():
headers = {
"User-Agent": "Mozilla/5.0(Macintosh;Intel Mac OS X 10_11_4) AppleWebKit/537.36(KTML,like Gecko) Chrome/52.0.2743.116 Safari/537.36"}
rrr = requests.get(value, headers=headers)
with open(filename+""+key+".jpg","wb") as f:
f.write(rrr.content)