用Python爬取色情网站的图片,技术宅的小玩具。在这里我将会向你详细介绍用Python下载一个色情网站图片的全部步骤,你会从中看到Python的简洁以及技术宅的无聊。
首先你应该应该有一个色情网站的网址,当然我不会给你的,自己找!!!我会告诉你其中的规律:
http://www.*****.com/htm/piclist【1】/【2】.htm
一个色情网站的图片区中,URL不同的只有【1】【2】两处,通过观察你可以发现,【1】处表示图片种类(丝袜美腿、清纯唯美、****、and so on),【2】处表示当前分类的第N页目录,所以。首先我们可以构建一个表示图片列表目录URL地址:
baseurl = 'http://www.*****.com/htm/piclist%s/%s.htm' urls = [baseurl % (x,y) for x in xrange(1,10) for y in xrange(1,10)]
这即是当前网站所有图片分类的所有前9页内容。
然后来分析每页目录的结构:
可以看出,每一条目录对应着一个<a>标签并被包含在一个<li>中,故以此可以构建一个分析HTML页面的解析器:
class ImgIdxPageParser(sgmllib.SGMLParser): ''' parse a image index page ''' def __init__(self): sgmllib.SGMLParser.__init__(self) self.imgurlList = [] self.tagList = [] self.ontitle = False def unknown_starttag(self, tag, attrs): if tag == 'li': self.tagList.append('li') elif tag == 'a' and len(self.tagList): self.imgurlList.append(WEBSITE + attrs[0][1]) elif tag == 'title': self.ontitle = True def unknown_endtag(self,tag): if tag == 'li': self.tagList.pop() elif tag == 'title': self.ontitle = False def handle_data(self, data): if self.ontitle: title = data.decode('utf-8').encode('gb2312').strip() self.title = title[:title.find('_')]
由于使用到sgmllib.SGMLParser,我们应该先import sgmlib。在ImgIdxPageParser中,我们通过title保存当前页面所处的分类,用imgurlList保存每一条目录地址。关于sgmllib.SGMLParser的介绍,请点击这里。
对此,我们构建一个函数,返回指定目录下的分类名称以及目录列表:
def getPageUrlList(page): ''' get title and all the pages list of a picIndex page ''' parser = ImgIdxPageParser() parser.feed(urllib2.urlopen(page).read()) return parser.imgurlList, parser.title
这个函数返回page页面里的所有目录条目以及所处的分区(丝袜美腿、清纯唯美、****、and so on)。
接着我们打开其中一个图片页分析如下:
理所当然,图片链接被放置在<img>的‘src’中,对此,我们构建第二个解析器——用于解析图片页面的每个图片的地址:
class ImagePageParser(sgmllib.SGMLParser): ''' parse a image page's image urls ''' def __init__(self): sgmllib.SGMLParser.__init__(self) self.imgurlList = [] def unknown_starttag(self, tag, attrs): if tag == 'meta' and attrs[0][1] == 'description': self.title = attrs[1][1].decode('utf-8').encode('gb2312').strip() elif tag == 'img': for key, value in attrs: self.imgurlList.append(value) if key == 'src' else None
在ImagePageParser中,我们通过title保存当前页面的标题,用imgurlList保存每一个图片的地址。同样我们需要构建一个函数来使用ImagePageParser,并返回所有的图片地址以及这些图片的标题:
def getImageUrlList(pageUrl): ''' get all image urls from a page ''' parser = ImagePageParser() parser.feed(urllib2.urlopen(pageUrl).read()) return parser.imgurlList, parser.title
getImageUrlList函数返回pageUrl页面里所有图片的地址以及这个页面的标题。
由于我们的得到的所有地址都是以列表形式展现出来,所以我们需要一个函数,一次性把一个列表中所有的图片下载下来:
def downloadImage(imgList, save=''): ''' download images of a list ''' if not (os.path.exists('save') and os.path.isdir(save)): try: os.makedirs(save) except Exception,e:pass for x in imgList: try: filename = save + '\\' + x[x.rfind('/') + 1:] print filename urllib.urlretrieve(x, filename) except Exception, e: print 'exception catched:', e
在downloadImage函数中,我们接收一个图片地址列表和一个保存路径(非必须,如果没有则在当前目录下保存),函数开始时if是为了保证在传入的save路径不存在时,先创建一个文件夹。然后是遍历图片地址的列表,通过urllib.urlretrieve()函数来下载每一个图片。关于urllib的详细介绍,请点击这里。我们在for里面使用try-except的目的是,当下载一张图片发生错误时(网络断线、文件IO出错或者任何未知错误时),不会让整个程序崩溃掉。
当准备工作完成以后,我们就可以开始下载图片了,剩下的任务就是对刚才所有的积木进行拼装整合了:
if __name__ == '__main__': basepath = 'G:\\__temp\\' baseurl = 'http://www.*****.com/htm/piclist%s/%s.htm' urls = [baseurl % (x,y) for x in xrange(1,10) for y in xrange(1,10)] for url in urls: try: pagelist, outtitle = getPageUrlList(url) print outtitle, pagelist for page in pagelist: imglist, intitle = getImageUrlList(page) downloadImage(imglist, save= basepath + outtitle + '\\' + intitle) except Exception, e: print 'excepiton catched:' , e
这就完成了对程序的组合,到此就可以实现自动下载色情网站的图片了,而且由于对标题的处理,我们得到的将会是按照网站上保存结构同样的目录层级。
当然程序到这里还有很多需要处理的,比如为了提高效率我们需要多线程的加入,对图片下载可能的错误做完整的处理等等,对此,请记住一句话:自力更生,丰衣足食!