#!/usr/bin/env python# -*- coding: utf-8 -*-#原廠模式def createDomTree(htmlStream,type='soup'): if type == "soup": return tnDomTreeWithSoup(htmlStream) if type == "lxml": return tnDomTreeWithlXml(htmlStream) return None #外部依賴的介面,它屏蔽了我具體使用的第三方庫class tnDomTree: #public def __init__(self,htmlStream): self.htmlStream = htmlStream def getLinkList(self): return self._getElementByTagName('a')#提取子類共有行為到基類 def getImageList(self): return self._getElementByTagName('img')#提取子類共有行為到基類 def elementToString(self,element): pass def getAttrValueOfElement(self,element,attName): pass #private def _getElementByTagName(self,tagName):#子類實現該方法 pass#使用BeautifulSoup的類from BeautifulSoup import BeautifulSoupclass tnDomTreeWithSoup(tnDomTree): def __init__(self,htmlStream): tnDomTree.__init__(self,htmlStream) self._tree = BeautifulSoup(self.htmlStream) def _getElementByTagName(self,tagName): return self._tree.findAll(tagName) def elementToString(self,element): return str(element) def getAttrValueOfElement(self,element,attName): if hasattr(element,attName): return str(element[attName]) else: return ""#使用lxmlfrom lxml.html import tostringfrom lxml.html.soupparser import fromstringclass tnDomTreeWithlXml(tnDomTree): def __init__(self,htmlStream): tnDomTree.__init__(self,htmlStream) self._tree = fromstring(self.htmlStream) def _getElementByTagName(self,tagName): list = [] for i in self._tree.iter(): if i.tag == tagName: list.append(i) return list def elementToString(self,element): return tostring(element) def getAttrValueOfElement(self,element,attName): if attName in set(element.keys()): return str(element.attrib[attName]) else: return ""if __name__ == "__main__": s1 = ''' <p>BEIAI</p> <p><img src="/attachment/28" alt=""></p> ''' print s1 domtree = createDomTree(s1,'soup') list = domtree.getImageList() for i in list: print domtree.getAttrValueOfElement(i,'src') print domtree.elementToString(i)
為什麼能抽出一個公用的介面出來?本質上是因為這些東西有相似性,而具體到代碼的設計,就應該設計成和其他類相似的API,否則類的設計就是不對的