最近在研读jdk源码,网上找了下资源,发现都不完整。
后来新发现了一个有完整源码的地方,主要包括了java,c,c++的东西,装逼需要,就想拿来玩玩。但是,找了好多种下载打开的方式,发现都不对。于是,我随手写了python爬虫,把他搞定。
1.1. 目标地址:http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/dddb1b026323/,打开后先自己看下,是否符合自己的需求;
1.2. 分析此结构下主要有两种形式,一是目录文件,二是最终文件,特征明显,可区分出最终结果;
1.3. 目录深度不确定,很自然地想到了递归;
1.4. 查询有效目录,很自然地想到了正则表达式;
1.5. 基于可能有中断的情况,可能需要进行断点下载,因此考虑加个简单的跳过功能;
1.6. 考虑可能出现重复下载某文件或目录的情况,耗费资源,因此加一个全局文件集,进行去重处理;
1.7. 由于该文件目录很规律,就直接沿用其目录结构了;
1.8. 考虑到本机环境可能不稳定,于是利用公司测试环境服务器;
1.9. 开工!
#!/usr/bin/python # -*- coding: UTF-8 -*- import urllib,urllib2 import re import os import HTMLParser dirbase = '/tmp' urlbase = 'http://hg.openjdk.java.net' url= urlbase + '/jdk8u/jdk8u/jdk/file/dddb1b026323/src' # 标识用于跳过目录至xx,以达到按需下载 skip_to_p = '' # 辅助跳过标识 skip_find = False; textmod ={'user':'amei'} textmod = urllib.urlencode(textmod) print(url) req = urllib2.Request(url = '%s%s%s' % (url,'?',textmod)) res = urllib2.urlopen(req) res = res.read() # 全局已搜寻过的文件集合,防重入 allflist = [] # 1. 找到content的表单,2. 找出有效的地址链接 table=re.findall(r'<tbody class="stripes2">(.+)<//tbody>',res, re.S) harr = re.findall(r'href="(/jdk8u[/w///._]+)">(?!/[up/])', table[0]) def down_src_recursion(harr): global allflist,skip_find; if(not harr): return False; i=0; arrlen = len(harr) print("in new dir cur...") if(len(allflist) > 1500): print('over 1500, cut to 800 exists...') allflist = allflist[-800:] for alink in harr: i += 1; # 对最后一个目录符号去除,防止无用的扫描 alink = alink.rstrip('/') if(skip_to_p and not skip_find): if(alink != skip_to_p): print('skip file, cause no find..., skip=%s,now=%s' % (skip_to_p, alink)) continue; else: skip_find = True; if(alink in allflist): print('目录已搜寻过:' + alink) continue; pa = dirbase + alink if(os.path.isfile(pa)): print('文件已存在,无需下载: ' + pa) continue; reqt = urllib2.Request(urlbase + alink) rest = urllib2.urlopen(reqt) rest = rest.read() allflist.append(alink) if(rest.find('class="sourcefirst"') > 0): print('这是个资源文件:%s %d/%d' % (alink, i, arrlen)) filename = alink.split('/')[-1] linearr = re.findall(r'<span id=".+">(.+)</span>', rest) fileObject = open(dirbase + alink, 'w') for line in linearr: try: # 文件存在特殊的html标识符,需要转换,但由于有非标准语言存在,可能抛出异常,需捕获 line = HTMLParser.HTMLParser().unescape(line) except UnicodeDecodeError as e: print('oops, ascii convert error accour:', e) fileObject.write(line + '/r/n') fileObject.close() else: print('这是目录:%s %d/%d' % (alink, i, arrlen)) if(not os.path.exists(pa)): print('创建目录:%s' % alink) os.makedirs('/tmp' + alink, mode=0777) ta=re.findall(r'<tbody class="stripes2">(.+)<//tbody>',rest, re.S) ha = re.findall(r'href="(/jdk8u[/w///._]+)">(?!/[up/])', ta[0]) down_src_recursion(ha) # go... down_src_recursion(harr);
python jdk-crawler.py
du -sh /tmp/jdk8u/
ok, 以上,就打完了。等测试环境下载完成后,再通过ftp搬到你电脑上了。