Fork me on GitHub
python抓取网页图片

python抓取网页图片

网页的图片大致是用Image导入的,使用的是相对路径,例如

<image src="image/bg.jpg"/>

通过匹配可以获取image/bg.jpg,与页面地址组合可以得到图片的地址

除了直接引入的图片,还有通过CSS,HTML引入的图片,也需要处理

复制代码
# -*- coding: utf-8 -*-
import urllib, httplib, urlparse
import sys
import re

def httpExists(url):
    host, path = urlparse.urlsplit(url)[1:3]
    if ':' in host:
        # port specified, try to use it
        host, port = host.split(':', 1)
        try:
            port = int(port)
        except ValueError:
            print 'invalid port number %r' % (port,)
            return False
    else:
        # no port specified, use default port
        port = None
    try:
        connection = httplib.HTTPConnection(host, port=port)
        connection.request("HEAD", path)
        resp = connection.getresponse( )
        if resp.status == 200:       # normal 'found' status
            found = True
        elif resp.status == 302:     # recurse on temporary redirect
            found = httpExists(urlparse.urljoin(url,resp.getheader('location', '')))
        else:                        # everything else -> not found
            print "Status %d %s : %s" % (resp.status, resp.reason, url)
            found = False
    except Exception, e:
        print e.__class__, e, url
        found = False
    return found

"""根据url获取文件名"""
def gGetFileName(url):
    if url==None: return None
    if url=="" : return ""
    arr=url.split("/")
    return arr[len(arr)-1]

"""根据url下载文件,文件名参数指定"""
def gDownloadWithFilename(url,savePath,file):
    #参数检查,现忽略
    try:
        urlopen=urllib.URLopener()
        fp = urlopen.open(url)
        data = fp.read()
        fp.close()
        print 'download file url :',url
        file=open(savePath + file,'w+b')
        file.write(data)
        file.close()
    except IOError:
        print "download error!"+ url

def gDownload(url,savePath):

    fileName = gGetFileName(url)
    gDownloadWithFilename(url,savePath,fileName)

def getRexgList(lines,regx,searchRegx):
    if lines==None : return 
    lists =[]
    for line in lines:
        ismatch = re.search(regx,line,re.IGNORECASE)
        if ismatch :
           
            matchs = re.search(searchRegx,line,re.IGNORECASE)
            if matchs != None:
                groups = matchs.groups()
                for str in groups:
                    if str not in lists:
                        lists.append(str)
    return lists
def checkLine(lines):
    for line in lines :
        matchs = re.search(r'url\((\S+)\)',re.IGNORECASE)
        if matchs != None :
            print matchs.groups()
def  getPageLines(url):
    if url==None : return
    if not httpExists(url): return 
    try:
        page = urllib.urlopen(url)   
        html = page.readlines()
        page.close()
        return html
    except:
        print "getPageLines() error!"
        return
def getCurrentPageImage(url,savePath):
    lines = getPageLines(url)
    print 'lines.length',len(lines)
   
    regxlists =  getRexgList(lines,r'src\s*="images(\S+)"',r'src\s*="(\S+)"')
    if regxlists==None: return 
    print 'getCurrentPageImage() images.length',len(regxlists)
    for jpg in regxlists:
        jpg =url + jpg
        gDownload(jpg,savePath)

def getCSSImages(link,savePath,url):
    lines = getPageLines(link)
    print 'lines.length',len(lines)
    regxlists =  getRexgList(lines,r'url\((\S+)\)',r'url\((\S+)\)')
    if regxlists==None: return 
    print 'getCurrentPageImage() images.length',len(regxlists)
    for jpg in regxlists:
        jpg =url + jpg
        gDownload(jpg,savePath)

"""根据url获取其上的相关htm、html链接,返回list"""
def gGetHtmlLink(url):
    #参数检查,现忽略
    rtnList=[]
    lines=getPageLines(url)
    regx = r"""href="?(\S+)\.htm"""
    for link in getRexgList(lines,regx,r'href="(\S+)"'):
        link =url + link
        if link not in rtnList:
            rtnList.append(link)
            print link
    return rtnList
"""根据url获取其上的相关css链接,返回list"""
def gGetCSSLink(url):
    #参数检查,现忽略
    rtnList=[]
    lines=getPageLines(url)
    regx = r"""href="?(\S+)\.css"""
    for link in getRexgList(lines,regx,r'href="(\S+)"'):
        link = url + link
        if link not in rtnList:
            rtnList.append(link)
    return rtnList   
def getPageImage(url,savePath):
    """getCurrentPageImage(url,savePath)"""

    """读取其他的CSS,html文件中的图片
    links=gGetHtmlLink(url)
    for link in links:
        print u'get images on link-html读取'
        getCurrentPageImage(link,savePath)"""
    links=gGetCSSLink(url)
    for link in links:
        print 'get images on link:',link
        getCSSImages(link,savePath,url)
if __name__ == '__main__':
    
    url = 'http://www.templatemo.com/templates/templatemo_281_chrome/'
    savePath = 'd:/tmp/'
    print 'download pic from [' + url +']'
    print 'save to [' +savePath+'] ...'
    getPageImage(url,savePath)
    print "download finished"
复制代码

具体使用的时候根据URL的情况,具体分析得到图片地址的方式。

 

红黑树:个人理解与Python实现

红黑树:个人理解与Python实现

【基本事实1】
红黑树是一种平衡的二叉查找树,无论插入还是删除操作都可以在O(lg n)内实现,而一般的二叉查找树则在极端情况下会退化为线性结构。
红黑树之所以是平衡的二叉查找树,是因为每个节点都有表示其颜色的域值:红或黑,在插入和删除操作的时候依据节点的颜色向平衡的方向调整。根本原因当然是由红黑树定义所决定的:
如果一个二叉查找树满足如下条件,那么它就称作红黑树:
1.每个节点要么是红色,要么是黑色
2.根结点是黑色
3.每个叶节点(NIL)为黑色
4.如果一个节点是红色,其儿子节点一定是黑色
5.对于每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑节点

【个人理解1】
红黑树的定义中,我认为有这些地方要注意:
1.每个节点只有一种颜色(后面删除节点的操作时引入的“额外一重黑色”则不满足此条件,所以一直要性质1调整)
2.定义中的叶节点是指NIL,它们都是黑色,而且没有子节点。根结点的父节点也是NIL。比如只有一个根节点的红黑树,它有两个叶节点。NIL是没有值的,只是一种存在。(我在Python的实现中,把NIL值都设定为None3.如果一个节点是红色的,它一定不是根结点,而且一定有父节点(父节点也一定是黑色的);如果它有儿子节点则一定是黑色儿子节点(每个节点如果左右儿子都是NIL,我认为它没有儿子)
4.性质5说的就是黑高度了

【基本事实2】
红黑树的旋转
红黑树在INSERTDELETE的过程中,会使用到旋转操作。红黑树有两种旋转:左旋和右旋

左旋x:从右图到左图的过程
右旋y:从左图到右图的过程 【个人理解21.并非每个节点在INSERTDELETE的过程中都需要旋转操作 2.左旋就是右儿子y取代父节点xx作为y的做儿子,y原来的左儿子b成为x现在的右儿子 3.右旋就是左旋的逆向过程 【基本事实3】 红黑树的插入 INSERT一个值的过程,就是在二叉查找树的INSERT操作基础上,根据红黑树性质做必要的调整,比如颜色变化,比如旋转,也就是INSERT_FIXUP的过程 插入的节点一般设定为红色然后再调整 【个人理解3】 假设要插入的节点为zINSERT操作就是把z放到树的最底层,然后用INSERT_FIXUP区调整。INSERT_FIXUP中要注意的是: 1.如果z的父节点是NIL(即:插入节点z之前红黑树为空),那么把z涂黑,并成为根结点(完成插入) 2.如果z的父节点是黑色的,不用调整(完成插入) 3.如果z的父节点是红色的: 3-0:如果z没有叔叔节点,那么: 3-0-0:如果z为右儿子,则左旋z的父节点,成为3-0-1 3-0-1:如果z为左儿子,则“父涂黑,爷涂红”,然后如果父节点是左儿子,则“爷右旋”,否则“爷左旋”(完成插入) 3-1:如果z的叔叔节点为黑色,那么: 3-1-0:如果z是右儿子,那么左旋z的父节点,转化为3-1-1 3-1-1:如果z是左儿子,那么“父涂黑,爷涂红”,然后如果父节点是左儿子,则“爷右旋”,否则“爷左旋”(完成插入) 3-2:如果z的叔叔节点为红色,那么“父涂黑,叔涂黑,爷涂红”,并对爷爷节点g调用INSERT_FIXUP过程 以上序号和《算法导论》中的对应关系:3-2对应case13-1-0对应case23-1-1对应case3 【基本事实41.红黑树删除一个节点的操作比较复杂,但也是在二叉查查找树的基础上,调用DELETE_FIXUP过程来调整 2.如果要删除的节点z,它有两个儿子,那么让z的值设定为z的后继节点y的值,然后删除y 3.如果要删除的节点z只有一个儿子x,那就让z的节点px成为“父子”。如果z原来是红色的,则不必调用DELETE_FIXUP过程,否则要调用 4.如果要删除的节点z没有儿子:那就直接删除z好了 5.删除节点时引入了“额外的一层黑色”,《算法导论》中文第二版P173这样说: “在RB—DELETE中,如果被删除的节点y是黑色的,则会产生三个问题。首先,如果y原来是根结点,而y的一个红色的孩子成为了新的根,这就问犯了性质2)。其次,如果xp[y](现在也是p[x])都是红的,就违反了性质4)。第三,删除y将导致先前包含y的任何路径上黑节点个数少1。因此,性质5)被y的一个祖先破坏了。不久者恶问题的一个办法就是把结点x视为还有额外的一重黑色。也就是说,如果将人以包含结点x的路径上黑节点个数加1,则在这种假设下,性质5)成立。当将黑节点y删除时,将其黑色“下推”至其子节点。现在为题变为结点x可能既不是红,又不是黑,从而违反了性质1)。结点x是双重黑色或红黑,这就分别给包含x的路径上黑结点个数贡献2个或1个。xcolor属性仍然是RED(如果x是红黑的)或BLACK(如果x是双重黑色)。换言之,一个结点额外的黑色反映在x指向它,而不是它的color属性。” 【个人理解41.当你想举反例推翻某个“结论”时,请注意,你的反例中的红黑树可能并不是红黑树;或者,它满足红黑树的定义,但无法判断是否能通过“每次插入一个节点”的方式生成。 2.因为有“额外一重黑色”的存在,《算法导论》中关于红黑树删除的case1中,调整前后的两幅图虽然“看上去是镜面对称”,但前者不满足性质5,调整后满足性质5 3.《算法导论》中关于红黑树删除的case2中,x现在为黑色,且有额外的一重黑色(就像是背负着子孙们的希望。。。),此时将xw都去掉一个黑色,然后使px)增加额外的一层黑色。由于w原本为黑色,则现在令w为红色即可。此时令new_x=p(x),若new_x原本为红色,置黑即可结束;否则,对new_x调用DELETE_FIXUP过程 4.DELETE_FIXUP过程,调整的是DELETE(z)过程中z的左/右儿子(z只有一个儿子时),或者z的后继的右儿子


我的代码:
#coding:utf8#author:HaxtraZ#description:红黑树,python实现


RED ='red'
BLACK ='black'class RBT:def __init__(self):self.items =[]self.root =Nonedef LEFT_ROTATE(self, x):# x是一个RBTnode
        y = x.right
        if y isNone:# 右节点为空,不旋转returnelse:
            beta = y.left
            x.right = beta
            if beta isnotNone:
                beta.parent = x

            p = x.parent
            y.parent = p
            if p isNone:# x原来是rootself.root = y
            elif x == p.left:
                p.left = y
            else:
                p.right = y
            y.left = x
            x.parent = y

    def RIGHT_ROTATE(self, y):# y是一个节点
        x = y.right
        if x isNone:# 右节点为空,不旋转returnelse:
            beta = x.right
            y.left = beta
            if beta isnotNone:
                beta.parent = y

            p = y.parent
            x.parent = p
            if p isNone:# y原来是rootself.root = x
            elif y == p.left:
                p.left = x
            else:
                p.right = x
            x.right = y
            y.parent = x

    def INSERT(self, val):
        z =RBTnode(val)
        y =None
        x =self.root
        while x isnotNone:
            y = x
            if z.val < x.val:
                x = x.left
            else:
                x = x.right

        z.PAINT(RED)
        z.parent = y

        if y isNone:# 插入z之前为空的RBTself.INSERT_FIXUP(z)elif y.color == RED:# z的父节点y为红色,需要fixup。# 如果z的父节点y为黑色,则不用调整if z.val < y.val:
                y.left = z
            else:
                y.right = z
            self.INSERT_FIXUP(z)def INSERT_FIXUP(self, z):# case 1:z为root节点ifself.root ==None:
            z.PAINT(BLACK)self.root = z
            return# case 2:z的父节点为黑色ifself.parent.color == BLACK:# 包括了z处于第二层的情况return# 下面的几种情况,都是z.parent.color == RED:# 节点y为z的uncle
        p = z.parent
        if p == p.parent.left:
            y = p.parent.right
        else:
            y = p.parent.left

        g = p.parent  # g为x的grandpa# case 3-0:z没有叔叔。即:y为NIL节点# 注意,此时z的父节点一定是REDif y isNone:if z == p.left:# 3-0-0:z为右儿子,则把p左旋# 转化为3-0-1或3-0-2的情况self.LEFT_ROTATE(p)
                p, z = z, p
            g.PAINT(RED)
            p.PAINT(BLACK)if g.left == p:# 3-0-1:p为g的左儿子self.RIGHT_ROTATE(g)else:# 3-0-2:p为g的右儿子self.LEFT_ROTATE(g)# case 3-1:z有黑叔elif y.color == BLACK:if p.right == z:# 3-1-0:z为右儿子,则左旋p# 转化为3-1-1或3-1-2self.LEFT_ROTATE(p)
                p, z = z, p

            p.PAINT(BLACK)
            g.PAINT(RED)if p == g.left:# 3-1-1:p为g的左儿子,则右旋gself.RIGHT_ROTATE(g)else:# 3-1-2:p为g的右儿子,则左旋gself.LEFT_ROTATE(g)# case 3-2:z有红叔# 则涂黑父和叔,涂红爷,g作为新的z,递归调用else:
            y.PAINT(BLACK)
            p.PAINT(BLACK)
            g.PAINT(RED)self.INSERT_FIXUP(g)def DELETE(self, val):
        curNode =self.root
        while curNode isnotNone:if val < curNode.val:
                curNode = curNode.left
            elif val > curNode.val:
                curNode = curNode.right
            else:# 找到了值为val的元素,正式开始删除if curNode.left isNoneand curNode.right isNone:# case1:curNode为叶子节点:直接删除即可if curNode ==self.root:self.root =Noneelse:
                        p = curNode.parent
                        if curNode == p.left:
                            p.left =Noneelse:
                            p.right =Noneelif curNode.left isnotNoneand curNode.right isnotNone:
                    sucNode =self.SUCCESOR(curNode)
                    curNode.val, sucNode.val  = sucNode.val, curNode.val
                    self.DELETE(sucNode.val)else:
                    p = curNode.parent
                    if curNode.left isNone:
                        x = curNode.right
                    else:
                        x = curNode.left
                    if curNode == p.left:
                        p.left = x
                    else:
                        p.right = x
                    x.parent = p
                    if curNode.color == BLACK:self.DELETE_FIXUP(x)


                curNode =NonereturnFalsedef FIND(self, val):classRBTnode:'''红黑树的节点类型'''def __init__(self, val):self.val = val
        self.left =Noneself.right =Noneself.parent =Nonedel PAINT(self, color):self.color = color

  

作者:HaxtraZ
除非另有声明,本网站采用知识共享 “署名 2.5中国大陆” 许可协议授权
 
分类: Python
 
分类: python
posted on 2013-08-25 16:16  HackerVirus  阅读(561)  评论(0编辑  收藏  举报