zoukankan      html  css  js  c++  java
  • 随手用python写一个下载jdk源码爬虫

      最近在研读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.0. 开工!

    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'        #/jdk,/hotspot
    skip_to_p = ''
    skip_find = False;
    textmod ={'user':'admin','password':'admin'}
    textmod = urllib.urlencode(textmod)
    print(url)
    req = urllib2.Request(url = '%s%s%s' % (url,'?',textmod))
    res = urllib2.urlopen(req)
    res = res.read()
    alink = re.findall(r'<a',res)
    allflist = []
    
    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)
      lock_conflict_jump_max = 2;   # 遇到文件锁时跳过n个文件,当前仍需跳过的文件数量
      lock_conflict_jumping = 0;
      print("in new dir cur...")
      if(len(allflist) > 1500):
         print('over 1500, cut to 50 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;
        lockfile=pa+'.tmp'
        if(os.path.isfile(lockfile)):
        lock_conflict_jumping = lock_conflict_jump_max;
    print('文件正在下载中,跳过+%s...: %s' % (lock_conflict_jumping, lockfile))continue; else: if(lock_conflict_jumping > 0):
    lock_conflict_jumping -= 1;
    print('文件正在下载中,跳过+%s...: %s' % (lock_conflict_jumping, lockfile))continue; # 首先根据后缀把下载中的标识标记好,因为网络下载时间更慢,等下载好后再加标识其实已为时已晚 if(pa.endswith(('.gif','.jpg','.png', '.xml', '.cfg', '.properties', '.make', '.sh', '.bat', '.html', '.c','.cpp', '.h', '.hpp', '.java', '.1'))): os.mknod(lockfile); 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)) if(not os.path.isfile(lockfile)): os.mknod(lockfile); filename = alink.split('/')[-1] linearr = re.findall(r'<span id=".+">(.+)</span>', rest) fileObject = open(dirbase + alink, 'w') for line in linearr: try: line = HTMLParser.HTMLParser().unescape(line) except UnicodeDecodeError as e: print('oops, ascii convert error accour:', e) fileObject.write(line + ' ') fileObject.close() os.remove(lockfile); 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

    4. 瞅瞅下载得咋样了

    du -sh /tmp/jdk8u/

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

  • 相关阅读:
    nginx设置缓存策略
    http缓存原理理解
    promise教程
    vue项目发布到github演示
    vue路由嵌套子路由不渲染
    hihocoder 1403 1407 1415 后缀数组*3 最长公共子串/最长不重叠重复出现的子串/最长k次重复子串
    hdu 4691 后缀数组+rmq 求子串lcp
    hdu1506+ luogu 1440 单调栈/单调队列裸题
    codeforces 873F 后缀数组+单调栈(fastio)
    HihoCoder
  • 原文地址:https://www.cnblogs.com/yougewe/p/9407243.html
Copyright © 2011-2022 走看看