小编身为建筑师,经常需要到各种建筑网站找项目的参考图片。然而这年头各个大师们的事务所网站大家都懂得,各种高冷或者炫酷的动画效果让人一次只能看一张图,要想更高效率的看图或者下载到高清大图就更加麻烦了。
那么身为新时代的设计师,有没有简单高效的方式来搞定这一切吗?
有!答案就是Python爬虫。
我们今天以著名结构建筑两栖大师卡拉特拉瓦的个人网站为例。简单介绍下怎样用Python爬虫高效获取大师的高清作品集。
密尔沃基美术馆
用爬虫获取大师的作品集,其实原理上跟浏览网页一样,都是先打开项目的页面,点开高清大图,然后保存图片,只不过python爬虫的速度很快而已。
因为是爬取图片,所以本次爬虫没有使用Selenium,而是选择了纯代码的方式,这样可以省下浏览器打开图片渲染页面的时间消耗。
整个爬虫分为四个步骤:
-
访问网站
-
找到有哪些项目,以及项目的详细介绍的网页
-
在项目详细介绍的网页找到高清大图的地址
-
下载图片
在最开始我们可以用任意一款python编辑器,新建一个空的.py的文件。然后在最开头的地方加入我们需要用到的程序包,本次爬虫用了Beautifulsoup包,如果没有安装可以按以下方法安装。
# Python 2+
pip install beautifulsoup4
# Python 3+
pip3 install beautifulsoup4
Beautifulsoup包安装方法,强烈推荐使用Anaconda,这些常用包都是默认配置好的。
import requests, re, os
from bs4 import BeautifulSoup
导入需要用到的包
1.我们需要访问到大师网站。
# 输入大师的网址,这里的r是转义符
project_url = r'https://calatrava.com/projects.html?all=yes'
# 访问网站的模块,以后需要访问网站的时候都会用到这个函数
def download_page(url):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'
}
data = requests.get(url, headers=headers).content.decode('utf-8')
return data
2.找到有哪些项目,以及项目的详细介绍的网址
我们可以通过F12调出浏览器的开发者工具,看看这个网页到底是怎么构成的。我们可以看到所有的项目信息都在一个<div>打头的大标签里。在这个标签中,每个项目又分别对应了一个<li>的标签,li标签的class名是odd或者even。利用Beautifulsoup的find_all方法,我们就可以拆分出这个页面中出现的每个项目的网页信息,而项目的详细地址
从页面的html语言中解析出项目地址
# 解析得到标题与项目地址的列表
# 拆分出:1.每个项目的信息
def parse_html(url):
html = download_page(url)
soup = BeautifulSoup(html, features='lxml')
project_list_part=soup.find("div",{"class":"mod_cal_project_list thumb_view block"})
project_list_soup = project_list_part.find_all('li', {'class': {'odd',"even"}})
return project_list_soup
# 在项目信息中提取项目的名称,得到一个列表
def get_project_title(project_list_soup):
project_title = []
for link in project_list_soup:
project_year = link.find('span', {'class': 'year'})
links = link.find('a')['href']
name = str(project_year.string) + '--'+ str(links[9:-5])
project_title.append(name)
return project_title
# 解析出每个项目的地址,得到一个列表
def get_project_link(project_list_soup):
project_link = []
for link in project_list_soup:
links = link.find('a')['href']
#因为项目的详细页面的默认状态是看文字介绍,所以还需要在后面加入一个进入画廊状态的字符串
links = str(r"https://calatrava.com/" + links+r"?view_mode=gallery")
project_link.append(links)
return project_link
3.我们需要在项目详细介绍的网页找到高清大图的地址。
我们依然按F12进入浏览器的开发者模式,进入Network标签页,找到项目的大图的实际地址。再通过大图的实际地址转到element标签页中进行查找,这样我们可以解析出隐藏在翻页动画背后的高清大图的存储结构。
在开发者模式的network标签页中找到高清大图的位置
用找到的高清大图的名称,回到element标签页中Ctrl+F查找这个名称
至此我们可以发现页面的动画效果是通过一个JavaScript代码实现的,而每个项目的大图都是结构化的存储在这段json对象中,那我们直接用正则表达式提取出来就好了。
# 解析项目子项页面,得到图片地址的列表
def parse_sub_html(project_link):
html = download_page(project_link)
project_soup = BeautifulSoup(html, features='lxml')
# 抓取JavaScript代码,解析出图片存放的实际地址
project_img_links_script=project_soup.find_all("script")
project_img_links=re.findall(r"'(?P<addr>files.*)', title",str(project_img_links_script))
for i in range(len(project_img_links)):
project_img_links[i]=str(r"https://calatrava.com/")+project_img_links[i]
# print(str(project_img_links_script))
print(project_img_links)
print("此项目大图数量 = "+len(project_img_links))
return project_img_links
4.最后保存图片即可
# 根据图片地址的列表,设定命名规则,保存图片
def save_img(links, name):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
os.makedirs('./Calatrava project img/', exist_ok=True)
t = 1
for link in links:
filename = str('./Calatrava project img/' + str(name) + '%s.jpg' % (repr(t)))
print("Downloading----",str(filename))
with open(filename, "wb") as img:
img.write(requests.get(link, headers=headers).content)
t += 1
至此我们每一个步骤的方法都写完了,最后的最后组装成一个main函数运行就可以搓手收图了。
def main():
soup = parse_html(project_url)
# 得到项目名称以及项目地址
name = get_project_title(soup)
link = get_project_link(soup)
print(link)
# 进入项目子项地址下载图片
# 引入项目代号t可以从第t个项目开始下载,以防网络错误
t = 0
while t < len(name):
# 考虑空项目地址引起download函数报错
if link[t] == "":
print("Skip it,Because it is null,Hurry coding,,Fix it later")
t += 1
else:
img_list = parse_sub_html(link[t])
print('Project Name is :', name[t])
save_name = str(repr(t + 1)+"-" + name[t])
save_img(img_list, save_name)
print('No %s is ok' % repr(t + 1))
t += 1
if __name__ == '__main__':
main()
运行状态
卡拉特拉瓦的事务所网站一共90个项目,630张高清大图,就这样可以自动下好了。而且这个爬虫基本可以覆盖市面上95%以上的事务所网站的构架了,稍微改改地址之类的操作就可以一虫多用,是不是真香!
本文仅做python爬虫的技术探讨,请各位在法律框架下谨慎使用。