27

随手用python写一个下载源码爬虫试试

 5 years ago
source link: http://www.cnblogs.com/yougewe/p/9407243.html?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近在研读jdk源码,网上找了下资源,发现都不完整。

后来新发现了一个有完整源码的地方,主要包括了java,c,c++的东西,装逼需要,就想拿来玩玩。但是,找了好多种下载打开的方式,发现都不对。于是,我随手写了python爬虫,把他搞定。

1. 思路分析

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. 开工!

2. 鲁棒的代码来一波

#!/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);

3. 让代码跑起来

python jdk-crawler.py

NrYNrqQ.png!web

4. 瞅瞅下载得咋样了

du -sh /tmp/jdk8u/

Qzuaau2.png!web

ok, 以上,就打完了。等测试环境下载完成后,再通过ftp搬到你电脑上了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK