您的位置:首页 > 编程语言 > Python开发

Python爬虫抓取虎扑论坛帖子图片

2017-03-16 13:15 549 查看
自从可以实现抓取文字了,自然要尝试更多的类型,比如图片。我是一个有逛虎扑论坛习惯的人,经常会发现有些帖子的图片挺好看的想保存下来,但是如果人为保存的话,一个帖子至少都有二三十张,这将是一个庞大的工作量,所以如果可以通过爬虫实现那该多好。

我本来打算写一个脚本像博客文章一样可以自动爬墙某个人发过的所有帖子,但是我后来发现,其实个人发的帖子有很多不同的属性,即使是kaka和剑魔独孤求败这样在jrs心目中专门发美女照片的楼主,也会发一些纯文字比如讨论帖,而且每个贴的质量都是参差不齐的,不一定是你希望的图片,所以我后来决定只是爬去一篇帖子就好了。

写的过程中遇到的了一个难题是保存的gif实际上是一张静态图,后来才发现我保存只是gif没有缓冲好之前的一张静态图片,重新用正则表达式取出真正的gif的url地址仔下载发现就可以打开为动图了。

def getImg(page):
print u"开始获取图片"
pattern =re.compile('<img src="https.*?png" data-original="(http.*?)" data-w=".*?" data-h=".*?"')
items=re.findall(pattern,page)
imglist=[]
for item in items:

imglist.append(item.encode('utf-8'))
print item
print u"\n\n\n\n\n\n\n\n\n\n"
pattern =re.compile('img class.*?img-gif.*?src=\'http.*?\.gif\' data-url=\'(http.*?\.gif)\'')
items2=re.findall(pattern,page)
for item in items2:
imglist.append(item.encode('utf-8'))
print item
print u"\n\n\n\n\n\n\n\n\n\n"
pattern =re.compile('<img src="(https://i.*?\,jpg)" data-w=".*?" data-h=".*?">')
items3=re.findall(pattern,page)
for item in items3:
imglist.append(item.encode('utf-8'))
print item
pattern =re.compile('<img src="(https://i.*?gif)" data-w=".*?" data-h=".*?"')
items4=re.findall(pattern,page)
for item in items4:

imglist.append(item.encode('utf-8'))
print item
print u"\n\n\n\n\n\n\n\n\n\n"
return imglist
这个是根据虎扑HTML source编写的获得图片url地址的函数,完全利用正则表达式的做法有一个弊端就是当网页修改了一点就要重新匹配,而且由于虎扑的贴子HTML比较复杂,我发现前三张图片和后面部分的图片HTML格式还不一样,还要顾及图片格式究竟是jpg,jpeg还是gif,所以测试了很久才能基本满足抓取所有图片,目前还没遇到例外。

def writeData(imglist,path):
x=1
for item in imglist:
#print item.endswith('gif')
if(item.endswith('gif')):
urllib.urlretrieve(item,path+'%s.gif'%x)
else:
urllib.urlretrieve(item,path+'%s.jpg'%x)
print u"正在保存第",x,u"张照片",u"  发现共有",len(imglist),u"张照片"
x=x+1
获取的图片格式不同写入的时候后缀名自然不同,我用endwith去判断了一下就可以正确写入了。
def getTitle(page):
pattern = re.compile('<h1 id="j_data" data-title="(.*?)" tid', re.S)
result = re.search(pattern,page)
result=result.group(1).strip()
result=re.sub(ur'\.','',result)
print "title:"+result
if result:
return result
else:
return None
另外遇到一个问题是当我获得某一个标题是用...结尾的时候会发现可以创建文件夹但不可以打开文件夹里面抓取的文件,会弹出文件目录错误的提示,所以我同sub函数将title里的小数点除去就可以做一个文件夹的名了。

以下就是源码啦:

# -*- coding: cp936 -*-

__author__ = 'Thor'
# -*- coding:utf-8 -*-
import re
import urllib
import urllib2
import os

def getHtml(url):
try:
print url
request=urllib2.Request(url)
response=urllib2.urlopen(url)
print "连接成功"
#print response.read().decode('utf-8')
return response.read().decode('utf-8')
except urllib2.URLError,e:
if hasattr(e,"reason"):
print u"连接失败,错误原因",e.reason
return None

def getInfo(page):
print u"开始获取文字"
pattern =re.compile('<font size=".*?">(.*?)</font>',re.S)
items=re.findall(pattern,page)
Info=[]
for item in items:
item=re.sub(r'<(S*?)[^>]*>.*?|<.*? /> ','',item)
item=item+"\n"
Info.append(item.encode('utf-8'))
print item
return Info

def getTitle(page): pattern = re.compile('<h1 id="j_data" data-title="(.*?)" tid', re.S) result = re.search(pattern,page) result=result.group(1).strip() result=re.sub(ur'\.','',result) print "title:"+result if result: return result else: return None

def setFileTitle(title):
if title is not None:

a992
File = open(path +title+"\\\\" + "Information.doc","w")
else:
File = open(path + "default.doc","w")
return File

def getImg(page): print u"开始获取图片" pattern =re.compile('<img src="https.*?png" data-original="(http.*?)" data-w=".*?" data-h=".*?"') items=re.findall(pattern,page) imglist=[] for item in items: imglist.append(item.encode('utf-8')) print item print u"\n\n\n\n\n\n\n\n\n\n" pattern =re.compile('img class.*?img-gif.*?src=\'http.*?\.gif\' data-url=\'(http.*?\.gif)\'') items2=re.findall(pattern,page) for item in items2: imglist.append(item.encode('utf-8')) print item print u"\n\n\n\n\n\n\n\n\n\n" pattern =re.compile('<img src="(https://i.*?\,jpg)" data-w=".*?" data-h=".*?">') items3=re.findall(pattern,page) for item in items3: imglist.append(item.encode('utf-8')) print item pattern =re.compile('<img src="(https://i.*?gif)" data-w=".*?" data-h=".*?"') items4=re.findall(pattern,page) for item in items4: imglist.append(item.encode('utf-8')) print item print u"\n\n\n\n\n\n\n\n\n\n" return imglist
def writeInfo(Info,File):
if(Info==None):
return
for item in Info:
File.write(item)
#print item

def writeData(imglist,path): x=1 for item in imglist: #print item.endswith('gif') if(item.endswith('gif')): urllib.urlretrieve(item,path+'%s.gif'%x) else: urllib.urlretrieve(item,path+'%s.jpg'%x) print u"正在保存第",x,u"张照片",u" 发现共有",len(imglist),u"张照片" x=x+1def mkdir(path):
path=path.strip()
isExists=os.path.exists(path)
if not isExists:
print u"创建了名为",path,u"的文件夹"
os.makedirs(path)
return True
else:
print u"名为",path,u"的文件夹已经创建"
return False

def start(html,path):
page=getHtml(html)
imglist=getImg(page)
title=getTitle(page)
path=path+title+"\\"
mkdir(path)
writeData(imglist,path)
File=setFileTitle(title)
Info=getInfo(page)
writeInfo(Info,File)

print u"请输入某个虎扑帖子的网址(注意请选择只看楼主)\n"
html=raw_input()
print html
path="C:\Users\Administrator\Desktop\Hupu\\"
start(html,path)



1.jpg



正在保存图片

2.jpg



gif形式可以用浏览器打开,我试过传入微信在聊天中可以当表情,前提是不能太大。

3.jpg



这就是爬取一个帖子的所有图片,并且按数字命名,


4.jpg

我还写了函数为了获得这个帖子的文本,存在一个叫information的doc文档中

5.jpg



将所有的文件夹保存在一个文件夹里。当然保存的地方是可以根据自己需要修改的。

总结:完全使用正则表达式而不借助其他类库帮助分析网页结构的方法虽然可行,但是不具有持久性,如果网页布局稍有改变代码可能就无效了。所以为了更好的抓取网络上的信息需要继续学习。

.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: