最近在网上看了很多的爬虫脚本,写的参差不齐,但是其中有很多写的非常的优秀,代码质量很高,规范性也很好,很具有代表性,非常值得我们去学习!~

写好一个python爬虫需要有以下几个必备条件:

1、足够好的代码规范(等号前后加空格、逗号后加空格等等),结构性封装性好重用性高。这需要时间和很多的训练。

2、在抓取网页的html源码后,快速找到自己想要的目标,准确的写出它的正则表达式。

3、得到目标内容后,准确进行一系列保存抓取等后续操作

之前的帖子中介绍过url,也就是网址,在我们抓取网页的过程中也要非常注意网页的各项细节,而且需要我们不断的积累经验,也需要细心的分析:

例:

http://tieba.baidu.com/p/3138733512?see_lz=1&pn=1

这是我们要抓去的一个百度贴吧帖子的url,主要是后面的一小串看的不是很明白吧。下面带大家细细分析一下:

“http://“                             代表资源传输使用http协议。

"tieba.baidu.com”          这是百度贴吧的二级域名,指向贴吧的服务器。

"/p/3138733512"           这是服务器中的某一个资源,也就是我们目标帖子的定位符。

"?see_lz=1&pn=1"      前半部分指的是是否只看楼主,后半部分指的是pagenumber页数第一页。

这样我们就完整分析了一个网页,比如说很多人喜欢看斗鱼:https://www.douyu.com/directory/game/LOL,或者CSDN的编辑页面:http://write.blog.csdn.net/postedit?type=edit这个网页应该很好分析吧,以后抓取各种网页的时候都要学会怎样去分析一个网页的url,这样我们才能写出更加壮硕的小爬虫~~。

我们可以将一个网页拆分成基础部分和参数部分,比如:

http://tieba.baidu.com/p/3138733512?see_lz=1&pn=1

我们将它拆为基础部分:http://tieiba.baidu.com/p/3138733512,参数部分为:?see_lz=1&pn=1

这样做的目的使我们可以在一定程度上控制想要访问的页面,通过修改参数就可以达到我们想要的目的。

下面我们来实现第一条

在Python中我们也可以运用面向对象的方法,定义一个百度贴吧BDTB的类,其中包含初始化函数和各种不同的抓取函数,相当于用这个类给我们的小爬虫做一身好看的衣服。在写任何爬虫的Python程序中,都可以用这种用类包装的方法,相当于结构化了自己的程序,也使用了面向对象的方法。

我们就先来看看完整的程序:

#coding=utf-8
import urllib2
import re
import sys
reload(sys)
sys.setdefaultencoding("utf-8")# 处理页面标签类
class Tool:# 去除img标签,7位长空格removeImg = re.compile('<img.*?>| {7}|')# 删除超链接标签removeAddr = re.compile('<a.*?>|</a>')# 把换行的标签换为\nreplaceLine = re.compile('<tr>|<div>|</div>|</p>')# 将表格制表<td>替换为\treplaceTD = re.compile('<td>')# 把段落开头换为\n加空两格replacePara = re.compile('<p.*?>')# 将换行符或双换行符替换为\nreplaceBR = re.compile('<br><br>|<br>')# 将其余标签剔除removeExtraTag = re.compile('<.*?>')def replace(self, x):x = re.sub(self.removeImg, "", x)x = re.sub(self.removeAddr, "", x)x = re.sub(self.replaceLine, "\n", x)x = re.sub(self.replaceTD, "\t", x)x = re.sub(self.replacePara, "\n    ", x)x = re.sub(self.replaceBR, "\n", x)x = re.sub(self.removeExtraTag, "", x)# strip()将前后多余内容删除return x.strip()class BDTB:def __init__(self,baseurl,lz):self.Baseurl = baseurl #基础部分self.Lz = '?see_lz='+str(lz)  #是否只看楼主参数部分self.tool = Tool()    #标签处理类self.file = Noneself.floor = 1#######需要设置为全局变量,在写入文件时用来分割楼层。def Getpage(self,pagenum):   #函数用来生成完整url,并抓取网页返回self.Pagenum = '&pn=' + str(pagenum)url = self.Baseurl+self.Lz+self.Pagenum  #生成完整urlrequest = urllib2.Request(url)Mypage = urllib2.urlopen(request)   #使用request,获取网页内容return Mypage.read().decode('utf-8')  #将编码方式解码为utf-8def Getpagenum(self,page):  #函数用来抓取网页中包含的帖子最大页数pattern = re.compile('<li class="l_reply_num.*?</span>.*?<span.*?>(.*?)</span>', re.S)pagenum = re.search(pattern, page)  #使用search()方法,抓取目标内容if pagenum:return pagenum.group(1).strip() #如果包含的话就返回页数(字符串形式)else:return Nonedef Gettitle(self,page):   #函数用来抓取网页中包含的帖子的标题,用来命名txt文件pattern = re.compile('<h3 class="core_title_txt.*?>(.*?)</h3>',re.S)result = re.search(pattern,page)if result:return result.group(1).strip()#注意search()和findall()的区别注意else:return None
#多次出现的格式,但是我们只需要一个,并且不需要保存成list格式,可以使用search()返回一个字符串即可def Getimg(self,page):   #函数用来抓取网页中包含的帖子中的目标图片链接result_img = re.findall('<img class="BDE_Image" src="(.*?)" pic_ext=.*?>', page, re.S) #只要是符合正则表达式的所有图片都需要保存result_imgs = []for item in result_img:content = "\n" + self.tool.replace(item) + "\n"result_imgs.append(content.encode('utf-8'))   #换行处理更加清晰return result_imgsdef Getcontent(self,page):    #函数用来抓取网页中包含的帖子中的目标楼层文字内容items = re.findall('<div id="post_content_.*?>(.*?)</div>',page, re.S)contents = []for item in items :content = "\n" + self.tool.replace(item) + "\n"   #这里使用到了便签的处理类contents.append(content.encode('utf-8'))  #换行处理更加清晰return contentsdef setfile(self,title):    #函数用来打开创建一个txt文件用来存储if title is not None:self.file = open(title + ".txt", "w+") #没有这个文件的话会话就自己创建else:self.file = open(u"百度贴吧" + ".txt","w+")def savefile(self,items):    #函数用来保存目标楼层文字内容for item in items:floorline = str(self.floor) + u'楼' + '——————————————————————————————'self.file.write(floorline)self.file.write(item)self.floor += 1def saveimg(self,result_img):  #函数用来保存目标楼层的目标图片链接for img in result_img:self.file.write(img)def start(self):    #开始函数,用来再次包装所有的函数以达到将内容写进txt文件的目的page1 = self.Getpage(1)pagenum = self.Getpagenum(page1)title = self.Gettitle(page1)self.setfile(title)if pagenum == 0:print '该链接已失效或为无效链接'else:print '开始写入数据'for i in range(1,int(pagenum)+1):print '正在写入第'+str(i)+'页信息'page=self.Getpage(i)self.savefile(self.Getcontent(page))self.saveimg(self.Getimg(page))print '数据写入完毕'print u'请输入帖子链接'
baseurl = str(raw_input())
seeLZ = raw_input("是否只获取楼主发言,是输入1,否输入0\n")
bdtb = BDTB(baseurl,seeLZ)  #类的实例化
bdtb.start()

咱们先不管一开始的Tool类,看下面的BDTB类,用来包装了我们所有的重要的函数。每个函数都有详细的介绍。

其中有几点需要着重注意的地方

1、findall()和search()之间的区别和用法。

findall()函数:返回的是所有满足其正则表达式的内容,形式为列表。

search()函数:返回的是第一个满足条件的匹配,形式为字符串或者是元组。

这里我们就可以看出为什么程序中有的需要使用findall,有的需要使用search()。例如:

我们要的是一个最大的页数,但是玩过贴吧都知道在页首和页尾都会显示最大页数,我们用正则表达式就会匹配到两个地方的内容,如果我们使用findall()函数,返回的是[5,5],但是我们只需要一个简单的5,就够了,这就需要search()的使用了。

学会在什么情况下分别使用这两种函数也是比较重要的

2、result.group(1).strip()

这样的表达是为了得到我们的目标结果。

group(),返回的是匹配到的一个或者多个子组,如果只有一个参数,那么就是字符串。多个参数返回的就是元组。这里的group(1)指的就是第一个参数

strip(),默认删除空白符(包括'\n', '\r', '\t', ' ')。

3、抓去了网页的html源码以后还是要仔细的观察、分析找到目标后,写出合适的正则表达式也是一个重点所在!~

再说我们多出的Tool类,这个类是对很多哦帖子分析得来的结果,你可以尝试单独输出一下没有经过标签处理类的楼层文字内容,会有很多想不到的标签出现,比如说空格、换行符、超链接等等,Tool类中给出了很多种情况。

在此我们又要讨论一种情况的发生,就是目标内容的内部包含了我们不想要的东西,比如说:“我喜欢<HVGgvjhhgu>Python”,我们想去除其中的<>内容,就需要用到re模块的sub()函数处理我们的目标内容。这也算是比较精髓的一种内容啦。

对于这个程序的改写,也非常容易,只要替换掉一些正则表达式即可。或者不想处理百度贴吧的帖子,想抓去淘宝链接的美图,也可以通过稍加修改来得到。

本例部分结果如下:

更新一下抓取其中的主要图片的例子,上一次我们已经得到了其中的图片链接,下面就是保存抓取了:

#coding=utf-8
import urllib2
import urllib
import re
import os
import sys
reload(sys)
sys.setdefaultencoding("utf-8")# 处理页面标签类
class Tool:# 去除img标签,7位长空格removeImg = re.compile('<img.*?>| {7}|')# 删除超链接标签removeAddr = re.compile('<a.*?>|</a>')# 把换行的标签换为\nreplaceLine = re.compile('<tr>|<div>|</div>|</p>')# 将表格制表<td>替换为\treplaceTD = re.compile('<td>')# 把段落开头换为\n加空两格replacePara = re.compile('<p.*?>')# 将换行符或双换行符替换为\nreplaceBR = re.compile('<br><br>|<br>')# 将其余标签剔除removeExtraTag = re.compile('<.*?>')def replace(self, x):x = re.sub(self.removeImg, "", x)x = re.sub(self.removeAddr, "", x)x = re.sub(self.replaceLine, "\n", x)x = re.sub(self.replaceTD, "\t", x)x = re.sub(self.replacePara, "\n    ", x)x = re.sub(self.replaceBR, "\n", x)x = re.sub(self.removeExtraTag, "", x)# strip()将前后多余内容删除return x.strip()class BDTB:def __init__(self,baseurl,lz):self.Baseurl = baseurl #基础部分self.Lz = '?see_lz='+str(lz)  #是否只看楼主参数部分self.tool = Tool()    #标签处理类self.file = Noneself.floor = 1#######需要设置为全局变量,在写入文件时用来分割楼层。self.name = 1def Getpage(self,pagenum):   #函数用来生成完整url,并抓取网页返回self.Pagenum = '&pn=' + str(pagenum)url = self.Baseurl+self.Lz+self.Pagenum  #生成完整urlrequest = urllib2.Request(url)Mypage = urllib2.urlopen(request)   #使用request,获取网页内容return Mypage.read().decode('utf-8')  #将编码方式解码为utf-8def Getpagenum(self,page):  #函数用来抓取网页中包含的帖子最大页数pattern = re.compile('<li class="l_reply_num.*?</span>.*?<span.*?>(.*?)</span>', re.S)pagenum = re.search(pattern, page)  #使用search()方法,抓取目标内容if pagenum:return pagenum.group(1).strip() #如果包含的话就返回页数(字符串形式)else:return Nonedef Gettitle(self,page):   #函数用来抓取网页中包含的帖子的标题,用来命名txt文件pattern = re.compile('<h3 class="core_title_txt.*?>(.*?)</h3>',re.S)result = re.search(pattern,page)if result:return result.group(1).strip()#注意search()和findall()的区别注意else:return None
#多次出现的格式,但是我们只需要一个,并且不需要保存成list格式,可以使用search()返回一个字符串即可def Getimg(self,page):   #函数用来抓取网页中包含的帖子中的目标图片链接result_img = re.findall('<img class="BDE_Image" src="(.*?)" pic_ext=.*?>', page, re.S) #只要是符合正则表达式的所有图片都需要保存result_imgs = []for item in result_img:content = "\n" + self.tool.replace(item) + "\n"result_imgs.append(content.encode('utf-8'))   #换行处理更加清晰return result_imgsdef Getcontent(self,page):    #函数用来抓取网页中包含的帖子中的目标楼层文字内容items = re.findall('<div id="post_content_.*?>(.*?)</div>',page, re.S)contents = []for item in items :content = "\n" + self.tool.replace(item) + "\n"contents.append(content.encode('utf-8'))  #换行处理更加清晰return contentsdef setfile(self,title):    #函数用来打开创建一个txt文件用来存储if title is not None:self.file = open(title + ".txt", "w+") #没有这个文件的话会话就自己创建else:self.file = open(u"百度贴吧" + ".txt","w+")def savefile(self,items):    #函数用来保存目标楼层文字内容for item in items:floorline = str(self.floor) + u'楼' + '——————————————————————————————'self.file.write(floorline)self.file.write(item)self.floor += 1def saveimg(self,result_img):  #函数用来保存目标楼层的目标图片链接for img in result_img:self.file.write(img)def saveImg(self, imageURL, fileName):u = urllib.urlopen(imageURL)data = u.read()f = open(fileName, 'wb')f.write(data)f.close()def saveImgs(self, images): # 保存多张写真图片print u"发现共有", len(images), u"张照片"for imageURL in images:splitPath = imageURL.split('.')fTail = splitPath.pop()if len(fTail) > 3:fTail = "jpg"fileName = str(self.name) + "." + fTailself.saveImg(imageURL, fileName)self.name += 1def mkdir(self, path):# 创建新目录isExists = os.path.exists(path)# 判断结果if not isExists:# 如果不存在则创建目录print u"偷偷新建了名字叫做", path, u'的文件夹'# 创建目录操作函数os.makedirs(path)return Trueelse:# 如果目录存在则不创建,并提示目录已存在print u"名为", path, '的文件夹已经创建成功'return Falsedef start(self):    #开始函数,用来再次包装所有的函数以达到将内容写进txt文件的目的page1 = self.Getpage(1)pagenum = self.Getpagenum(page1)title = self.Gettitle(page1)self.setfile(title)if pagenum == 0:print '该链接已失效或为无效链接'else:print '开始写入数据'for i in range(1,int(pagenum)+1):print '正在写入第'+str(i)+'页信息'page = self.Getpage(i)self.mkdir(str(i))self.savefile(self.Getcontent(page))self.saveImgs(self.Getimg(page))print '数据写入完毕'print u'请输入帖子链接'
baseurl = str(raw_input())
seeLZ = raw_input("是否只获取楼主发言,是输入1,否输入0\n")
bdtb = BDTB(baseurl,seeLZ)  #类的实例化
bdtb.start()

Python爬虫实战(1)——百度贴吧抓取帖子并保存内容和图片相关推荐

  1. Python爬虫实战(4):抓取淘宝MM照片

    Python爬虫入门(1):综述 Python爬虫入门(2):爬虫基础了解 Python爬虫入门(3):Urllib库的基本使用 Python爬虫入门(4):Urllib库的高级用法 Python爬虫 ...

  2. Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺

    其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语 ...

  3. Python爬虫实战(1):抓取毒舌电影最新推送

    ​ update:6/11/2017 由于毒舌电影公众号被关闭账号,源码已失效,可参考并调整相关参数以适配网站上其他公众号文章的抓取,望周知. ~~~~~~~~~~~ 作为一个电影爱好者," ...

  4. Python爬虫实战:手机APP数据抓取分析!谁说不能爬取app数据的?

    大多数手机APP里面返回的是json格式数据,或者一堆加密过的数据 .这里以超级课程表APP为例,使用python抓取超级课程表里用户发的话题.主要是练习python爬取app的一些方式和技巧. 1. ...

  5. Python爬虫实战(二):抓取京东苹果手机评价

    目录 1. 网站分析 2. 示例代码 3. 注意事项 1. 网站分析 本文实现的爬虫是抓取京东商城指定苹果手机的评论信息.使用 requests 抓取手机评论 API 信息,然后通过 json 模块的 ...

  6. Python爬虫实战(2)之爬取NBA球队各个球员头像图片

    1.目标页面 2.页面分析 1.每个队的球员列表都在 class="team_name"的span下的a标签的href下 2.每个球员的头像图标url 为 class=" ...

  7. python爬取app播放的视频,Python爬虫工程师必学——App数据抓取实战视频教程

    爬虫分为几大方向,WEB网页数据抓取.APP数据抓取.软件系统数据抓取.本课程主要为同学讲解如何用python实现App数据抓取,课程从开发环境搭建,App爬虫必备利器详解,项目实战,到最后的多App ...

  8. Python爬虫 | 斗图网表情包抓取

    Python爬虫 | 斗图网表情包抓取 1.数据来源分析 2.制作div_list 3.发起请求 4.保存图片 5.批量获取 6.完整代码 声明 1.数据来源分析   打开斗图吧的主页,发现网址非常有 ...

  9. Python 爬虫实战2 百度贴吧帖子

    爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 本篇目标 对百度贴吧的任意帖子进行抓取 指定是否只抓取楼主发帖内容 将抓取到的内容分析并保存到文件 1.URL格式的确定 首先, ...

最新文章

  1. 风投报告:2017下半年VR/AR娱乐领域投资额同比上升79% 【52翻译】
  2. python做图像识别好还是c++好_OpenCV人脸检测(C++/Python)
  3. hyperworks2018安装教程
  4. VMware workstation 8.0上安装VMware ESXI5.0
  5. 不止代码:ybtoj-消除木块(区间DP)
  6. Command 传参的几种方式
  7. Spring Cloud实战小贴士:turbine如何聚合设置了context-path的hystrix数据
  8. 洛谷P1087 FBI树
  9. html+分割字符,sql拆分字符串split
  10. Google推荐的15条军规:HTML5代码规范
  11. 使用python模块 将中文大写汉字转化成阿拉伯数字
  12. oracle excel导入卡死 新解决办法
  13. 一起学JAVA线程-JAVA Thread的基础
  14. 等效于35mm相机焦距的计算方法
  15. 用python写一个PDF翻译软件
  16. 京东实习生招聘面试小记
  17. ubuntu16.04 鼠标右键没有压缩/解压 选项
  18. MATLAB toc使用
  19. 清华大学操作系统课程实验
  20. [元带你学NVMe协议] ] 插槽接口(M.2 / mSATA / SATA )、总线(PCIE / SATA )、传输协议(NVME / AHCI) 图解

热门文章

  1. 笔记1 标识符与基本数据类型
  2. 模仿扇贝短文阅读页面
  3. machinations游戏经济系统验证工具
  4. 【小甲鱼Python】文件:因为懂你,所以永恒课后作业
  5. 项目五 定期存款利息计算器
  6. HW | 安装RTXA6000的注意事项 driver不匹配PKCS#7 signature not signed with a trusted key的修复
  7. 404丨天朝BAT者……牛么?
  8. 手握国企offer,33岁程序员不按常理出牌,网友炸了!
  9. 有关于Boolean的使用
  10. 我最推荐的少儿重疾保险性价比排行榜