用 Python 抓漫画(2011-01-21)

作者: Pope怯懦懦地 | 来源:发表于2017-12-09 17:28 被阅读60次

    我现在只追海贼王、火影、死神这三部漫画,一般在SF在线漫画上看。这地方的好处就是看漫画的时候点一下图片就会翻下一页,不像有些文章非要点“下一页”,还整得贼小,周围都是广告。但有时加载图片会发生错误,显示一半就罢工了,无论你怎么刷新都没用。

    今天看漫画的时候(一般是周四更新)突然想何不把漫画抓下来看呢。于是,我看了一下网页源码,发现它每张图片会附带一个随机数,猜都没得猜,比如,火影第524话的第1页 http://hotpic.sfacg.com/Pic/OnlineComic1/Naruto/524/ [1]。没办法,继续看源码。居然发现有个 js 文件包含了这一话所有图片的网址

    兴奋

    接下来的问题是一个古老的问题,用什么语言呢?我决定尝尝鲜,Python吧,不说它擅长网络事务么。搜了一下,决定用 urllib 库

    先把js文件抓下来:

    import urllib  
    str = urllib.urlopen('http://hotpic.sfacg.com/Utility/4/523.js').read()  
    str = urllib.quote(str).replace("/n", " ").replace("%20", " ").replace("%22", "/"").replace("%3A", ":").replace("%3B", ";").replace("%3D", "=")  
    print str  
    

    解释一下,由于是 js 文件,而且有中文编码,所以用quote()先编个码。这时,汉字不管它,但有些符号也跟着变了,比如,空格是“%20”,冒号是“%3A”,……,详见

    下面是把 url 指向的图片抓下来(暂时放桌面吧):

    import re  
    count = 1  
    for m in re.finditer(r'/"(http:[//w/.]+png)/"', str):  
        print "url: ", m.group(1)  
        print "end url/n"  
          
        url = m.group(1)  
        path = r"/Users/Pope/Desktop/%d.png" % count   
        count += 1  
        data = urllib.urlretrieve(url,path) 
    

    这里多亏了urlretrieve(url, filename)老兄,它负责把url所指的东西抓下来写进filename里。

    顺便复习一下正则表达式:

    Python的正则表达式模块叫re

    import re  
    

    常用的函数有这么几个:

    • match()search(),功能类似,但match()只从头匹配,而search()则可以匹配任意位置。
    >>> re.match("c", "abcdef")  # No match  
    >>> re.search("c", "abcdef") # Match  
    <_sre.SRE_Match object at ...>  
    
    • split()
    >>> re.split('/W+', 'Words, words, words.')  
    ['Words', 'words', 'words', '']  
    
    • findall()finditer()
    >>> re.findall("(/w+)", "Pope is a dog.")  
    ['Pope', 'is', 'a', 'dog']  
    
    >>> for m in re.finditer("(/w+)", "Pope is a dog."):  
    ...     print m.group()  
    ...   
    Pope  
    is  
    a  
    dog 
    
    • sub(pattern, repl, string),把string中所有匹配pattern的子串全部替换为repl
    >>> re.sub(r"(/w+)", r"@/1@","Pope is a dog.")  
    '@Pope@ @is@ @a@ @dog@.'  
    
    • group(), start(), end(), span():用于查询匹配结果,group()返回被匹配的字串,start()end()分别返回匹配的开始和结束位置,span()返回一个元组(开始位置,结束位置)。详见官方说明 Python 正则表达式操作指南

    P.S. 有个哥们写了个比较详细的 urllib 介绍

    P.P.S. Mac 上看漫画推荐 Simple Comic ,可以直接看压缩文件。所以,最好把下载下来的png图片打个包:

    import zipfile   
    import glob  
    import os  
    directory = "/Users/Pope/Desktop/"  
    f = zipfile.ZipFile( directory + 'naruto_523.zip', 'w' )   
    for img in glob.glob( os.path.join( directory, '*.png' ) ):  
        f.write( img )  
    f.close()  
    

    完整代码:

    import urllib  
      
    one_piece_url = "http://hotpic.sfacg.com/Utility/2/"  
    n = "640"  
    comic_url = one_piece  
    comic_name = "OnePiece"  
      
    str = urllib.urlopen(comic_url + n + ".js").read()  
    url_encoding = [["\n", " "], ["%20", " "], ["%22", '"'], ["%3A", ":"], ["%3B", ";"], ["%3D", "="], ["%5B", "["], ["%5D", "]"]]  
    pages = urllib.quote(str)  
    for pair in url_encoding:  
        pages = pages.replace(pair[0], pair[1])  
    print "js: " + pages  
    print "end js\n"  
      
    import re  
    count = 1  
    for m in re.finditer(r'(http:[\w./]+.png)', pages):  
        print "url: ", m.group(1)  
        print "end url\n"  
      
        url = m.group(1)  
        path = r"/Users/Pope/Desktop/%d.png" % count  
        count += 1  
        data = urllib.urlretrieve(url,path)  
      
    import zipfile  
    import glob  
    import os  
    directory = "/Users/Pope/Desktop/"  
    f = zipfile.ZipFile( directory + comic_name + n + '.zip', 'w' )  
    for img in glob.glob( os.path.join( directory, '*.png' ) ):  
        f.write( img )  
        os.remove( img )  
    f.close()  
    

    1. UPDATE 2017-12-09: 现在这个网页已经失效了。

    相关文章

      网友评论

        本文标题:用 Python 抓漫画(2011-01-21)

        本文链接:https://www.haomeiwen.com/subject/bacpixtx.html