这几天发现了一个很有意思的网站《Astronomy Picture of the Day Archive》,翻译过来就是:天文图片的每日档案。https://link.zhihu.com/?target=https%3A//apod.nasa.gov/apod/archivepix.html
天文图片的每日档案
这里我们写一个爬虫,将这些图片爬取下来,慢慢欣赏宇宙的神奇。
上几张图。。。
这张图是1995年放在天文图片的每日档案的第一张图,虽然简陋,但是它标志着人类对于宇宙探索的开始,标志着人类对于宇宙的敬畏。
这张图曾用于红帽linux的桌面,那是作者还是一个懵懂的少年,第一次看到这张图,兴奋不已,深深地被地球母亲的美貌所震撼,那时想着,找女朋友一定要找一个像这张图片所包含的某种高贵的女孩。。。。哈哈哈[捂脸]
闲言少叙,说爬虫吧!
先看看这个网页吧:
这个网页是一个静态网页,没有动态的技术实现,服务器应该比较远,打开网页的速度比较慢。
截止今天,整个网页有8471张照片,我们需要先在首页获取到所有子页面的URL,然后再依次进入子页面,保存图片。由于子页面比较多,为了节省时间,便使用多线程技术来爬取。
代码如下:
首先引入必要的包:
import requests #
from lxml import etree
from urllib import request
import threading
然后定义全局信息
#定义请求头信息
hreaders = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36'
}
#定义主页面URL
url = 'https://apod.nasa.gov/apod/archivepix.html'
#定义URL主体
domain_url = 'https://apod.nasa.gov/apod/'
#定义全局URL列表
gphoto_url = []
#定义全局锁
gLock = threading.Lock()
然后实现从首页面中获取所有子页面URL的接口:
#获取所有子页面的URL
def get_all_photo_url(main_url):
res = requests.get(url=main_url,headers=hreaders)
text = res.text
html = etree.HTML(text)
b_infos = html.xpath("//body/b//a/text()")
b_urls = html.xpath("//body/b//a/@href")#利用xpath获取子页面的URL
for b_url in b_urls:
gphoto_url.append(domain_url+b_url)#添加URL主体,保存到全局URL列表中
实现下载子页面中的图片的类:
由于我们要用多线程实现,所以该类集成线程类(threading),在该类中重新实现run方法,
在上面,我们已经将所有子接口的URL全部放在了全局URL列表中,在请求这些URL时,采用从列表最有一个URL开始,逆向爬取,每爬取一个URL,就删除一个URL,直到这些URL全部删除,则结束。在每个现场读取URL时,为避免其他线程也在读取,从而产生的重复爬取,这种情况,实现一个线程锁,确保每次只有一个线程操作URL列表。代码如下:
class Get_photo(threading.Thread):
global gphoto_url#声明列表
def run(self):
while True:
gLock.acquire()#开锁
le = len(gphoto_url)#获取列表的长度,并判断,如果为0,则退出
if le == 0:
gLock.release()#释放锁
break
p_url= gphoto_url[le-1]#取出一个URL,
gphoto_url.pop()#将取出的URL删除
gLock.release()#释放锁
try:
resp = requests.get(url = p_url,headers=hreaders)#请求URL
self.get_info(resp)
except:
pass
#保存图片
def get_info(self,resps):
text = resps.text
html = etree.HTML(text)
img_u = html.xpath("//a[1]/@href")[0]
imgu = domain_url + img_u
img_name = img_u.split("/")[-1]
try:
request.urlretrieve(imgu,img_name)#将图片保存
print('%s下载完成!,线程号:%s'%(img_name,threading.current_thread()))
except:
pass
如下:为爬到的图片,不禁感叹,大自然真实鬼斧神工,宇宙真是浩瀚又奇妙!