Python 正则表达式爬虫使用案例解析


Posted in Python onSeptember 23, 2019

现在拥有了正则表达式这把神兵利器,我们就可以进行对爬取到的全部网页源代码进行筛选了。

下面我们一起尝试一下爬取内涵段子网站:

http://www.neihan8.com/article/list_5_1.html

打开之后,不难看出里面一个一个非常有内涵的段子,当你进行翻页的时候,注意url地址的变化:

  • 第一页url: http: //www.neihan8.com/article/list_5_1 .html
  • 第二页url: http: //www.neihan8.com/article/list_5_2 .html
  • 第三页url: http: //www.neihan8.com/article/list_5_3 .html
  • 第四页url: http: //www.neihan8.com/article/list_5_4 .html

这样我们的url规律找到了,要想爬取所有的段子,只需要修改一个参数即可。

我们就开始一步一步将所有的段子爬取下来吧。

第一步:获取数据

1. 按照我们之前的用法,我们需要一个加载页面的方法。

这里我们统一定义一个类,将url请求作为一个成员方法处理。

我们创建了一个文件,叫duanzi_spider.py

然后定义一个Spider类,并且添加一个加载页面的成员方法。

import urllib2
class Spider:
  """
    内涵段子爬虫类
  """
  def loadPage(self, page):
    """
      @brief 定义一个url请求网页的方法
      @param page需要请求的第几页
      @returns 返回的页面url
    """
    url = "http://www.neihan8.com/article/list_5_" + str(page)+ ".html"
    #user-Agent头
    user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT6.1; Trident/5.0"
    headers = {"User-Agent":user_agent}
    req = urllib2.Request(url, headers = headers)
    response = urllib2.urlopen(req)
    print html

以上的loadPage的实现思想想必大家都应该熟悉了,需要注意定义python类的成员方法需要额外添加一个参数self.

2.写main函数测试一个loadPage方法

if __name__ == "__main__":
  """
    =====================
      内涵段子小爬虫
    =====================
  """
  print("请按下回车开始")
  raw_input()
  
  #定义一个Spider对象
  mySpider = Spider()
  mySpider.loadPage(1)

程序正常执行的话,我们会在皮姆上打印了内涵段子第一页的全部html代码。但是我们发现,html中的中文部分显示的可能是乱码。

那么我们需要简单的将得到的网页源代码处理一下:

def loadPage(self, page):
  """
    @bridf 定义一个url请求网页的方法
    @param page 需要请求的第几页
    @returns 返回的页面html
  """
  url = "http://www.neihan8.com/article/list_5_"+str(page)+".html"
  #user-agent头
  user-agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT6.1; Trident/5.0"
  headers = {"User-Agent":user-agent}
  req = urllib2.Request(url, headers = headers)
  response = urllib2.urlopen(req)
  html = response.read()
  gbk_html = html.decode("gbk").encode("utf-8")
  return gbk_html

注意:对于每个网站对中文的编码各自不同,所以html.decode("gbk")的写法并不是通用的,根据网站的编码而异。

第二步:筛选数据

接下来我们已经得到了整个页面的数据。但是,很多内容我们并不关心,所以下一步我们需要筛选数据。如何筛选,就用到了上一节讲述的正则表达式

首先

import re

然后,我们得到的gbk_html中进行筛选匹配。

我们需要一个匹配规则

我们可以打开内涵段子的网页,鼠标点击右键"查看源代码"你会惊奇的发现,我们需要的每个段子的内容都是在一个<div>标签中,而且每个div标签都有一个属性class="f18 mb20"

根据正则表达式,我们可以推算出一个公式是:

<div.*?class="f18 mb20">(.*?)</div>

这个表达式实际上就是匹配到所有div中class="f18 mb20"里面的内容(具体可以看前面介绍)

然后这个正则应用到代码中,我们会得到以下代码:

def loadPage(self, page):
  """
    @brief 定义一个url请求网页的办法
    @param page 需要请求的第几页
    @returns 返回的页面html
  """
  url = "http://www.neihan8.com/article/list_5_" +str(page) + ".html"
  #User-Agent头
  user-agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT6.1; Trident/5.0" 

  headers = {"User-Agent":user-agent}
  req = urllib2.Request(url, headers=headers)
  response = urllib2.urlopen(req)

  html = response.read()

  gbk_html = html.decode("gbk").encode("utf-8")

  #找到所有的段子内容<div class="f18 mb20"></div>
  #re.S 如果没有re.S,则是只匹配一行有没有符合规则的字符串,如果没有则匹配下一行重新匹配
  #如果加上re.S,则是将所有的字符串按一个整体进行匹配
  pattern = re.compile(r'<div.*?class="f18 mb20">(.*?)</div>', re.S)
  item_list = pattern.findall(gbk_html)
  return item_list
def printOnePage(self, item_list, page):
  """
    @brief 处理得到的段子列表
    @param item_list 得到的段子列表
    @param page处理第几页
  """
  print("*********第%d页,爬取完毕...******"%page)
  for item in item_list:
    print("===============")
    print ite

这里需要注意一个是re.S是正则表达式中匹配的一个参数。

  • 如果没有re.S则是只匹配一行有没有符合规则的字符串,如果没有则下一行重新匹配。
  • 如果加上re.S则是将所有的字符串按一个整体进行匹配,findall将匹配到的所有结果封装到一个list中。
  • 如果我们写了一个遍历item_list的一个方法printOnePage()。ok程序写到这,我们再一次执行一下。
python duanzi_spider.py

我们第一页的全部段子,不包含其他信息全部的打印了出来.

  • 你会发现段子中有很多<p>,</p>很是不舒服,实际上这个是html的一种段落的标签。
  • 在浏览器上看不出来,但是如果按照文本打印会有<p>出现,那么我们只需要把我们的内容去掉即可。
  • 我们可以如下简单修改一下printOnePage()
def printOnePage(self, item_list, page):
  """
    @brief 处理得到的段子列表
    @param item_list 得到的段子列表
    @param page 处理第几页
  """
  print("******第%d页,爬取完毕*****"%page) 
  for item in item_list:
    print("============")
    item = item.replace("<p>", "").replace("</p>", "").replace("<br />", "")
    print item

第三步:保存数据

我们可以将所有的段子存放在文件中。比如,我们可以将得到的每个item不是打印出来,而是放在一个叫duanzi.txt的文件中也可以。

def writeToFile(self, text):
  """
    @brief 将数据追加写进文件中
    @param text 文件内容
  """
  myFile = open("./duanzi.txt", "a") #a追加形式打开文件 
  myFile.write(text)
  myFile.write("-------------------------")
  myFile.close()

然后我们将所有的print的语句改写成writeToFile(), 当前页面的所有段子就存在了本地的duanzi.txt文件中。

def printOnePage(self, item_list, page):
  """
    @brief 处理得到的段子列表
    @param item_list 得到的段子列表
    @param page 处理第几页
  """
  print("***第%d页,爬取完毕****"%page)
  for item in item_list:
    item = item.replace("<p>", "").replace("</p>", "").replace("<br />". "")

    self.writeToFile(item)

第四步:显示数据

接下来我们就通过参数的传递对page进行叠加来遍历内涵段子吧的全部段子内容。

只需要在外层加上一些逻辑处理即可。

def doWork(self):
  """
    让爬虫开始工作
  """
  while self.enable:
    try:
      item_list = self.loadPage(self.page)
    except urllib2.URLError, e:
      print e.reason
      continue

  #将得到的段子item_list处理
  self.printOnePage(item_list, self.page)
  self.page += 1
  print "按回车继续...."
  print "输入quit退出"

  command = raw_input()
  if(command == "quit"):
    self.enable = False
    break

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python struct.unpack
Sep 06 Python
python实现中文分词FMM算法实例
Jul 10 Python
linecache模块加载和缓存文件内容详解
Jan 11 Python
Python利用字典将两个通讯录文本合并为一个文本实例
Jan 16 Python
pandas去除重复列的实现方法
Jan 29 Python
python async with和async for的使用
Jun 20 Python
用Python爬取QQ音乐评论并制成词云图的实例
Aug 24 Python
浅谈Python3多线程之间的执行顺序问题
May 02 Python
Python利用myqr库创建自己的二维码
Nov 24 Python
python可视化 matplotlib画图使用colorbar工具自定义颜色
Dec 07 Python
解决Python import .pyd 可能遇到路径的问题
Mar 04 Python
LyScript实现绕过反调试保护的示例详解
Aug 14 Python
python处理document文档保留原样式
Sep 23 #Python
python 进程间数据共享multiProcess.Manger实现解析
Sep 23 #Python
python程序 线程队列queue使用方法解析
Sep 23 #Python
python程序 创建多线程过程详解
Sep 23 #Python
详解python播放音频的三种方法
Sep 23 #Python
Python进程间通信 multiProcessing Queue队列实现详解
Sep 23 #Python
python程序中的线程操作 concurrent模块使用详解
Sep 23 #Python
You might like
PHP 和 HTML
2006/10/09 PHP
php+MySQL判断update语句是否执行成功的方法
2014/08/28 PHP
php使用number_format函数截取小数的方法分析
2016/05/27 PHP
php+ajax实现无刷新文件上传功能(ajaxuploadfile)
2018/02/11 PHP
实现PHP中session存储及删除变量
2018/10/15 PHP
PHP简单实现图片格式转换(jpg转png,gif转png等)
2019/10/30 PHP
HTML5如何适配 iPhone IOS 底部黑条
2021/03/09 HTML / CSS
jQuery实现表单input中提示文字value随鼠标焦点移进移出而显示或隐藏的代码
2010/03/21 Javascript
复制小说文本时出现的随机乱码的去除方法
2010/09/07 Javascript
js实现屏蔽默认快捷键调用自定义事件示例
2013/06/18 Javascript
JQuery文本改变触发事件如聚焦事件、失焦事件
2014/01/15 Javascript
深入理解JavaScript系列(25):设计模式之单例模式详解
2015/03/03 Javascript
详解如何在react中搭建d3力导向图
2018/01/12 Javascript
angular基于ng-alain定义自己的select组件示例
2018/02/23 Javascript
vue-cli扩展多模块打包的示例代码
2018/04/09 Javascript
解决Vue axios post请求,后台获取不到数据的问题方法
2018/08/11 Javascript
elementUI select组件value值注意事项详解
2019/05/29 Javascript
Python中的类与对象之描述符详解
2015/03/27 Python
python实现机械分词之逆向最大匹配算法代码示例
2017/12/13 Python
Django contenttypes 框架详解(小结)
2018/08/13 Python
Python实现App自动签到领取积分功能
2018/09/29 Python
tensorflow 模型权重导出实例
2020/01/24 Python
Python3如何判断三角形的类型
2020/04/12 Python
利用简洁的图片预加载组件提升html5移动页面的用户体验
2016/03/11 HTML / CSS
Ever New美国:澳大利亚领先的女装时尚品牌
2019/11/28 全球购物
前台文员岗位职责
2013/12/28 职场文书
个人评价范文分享
2014/01/11 职场文书
简历的自我评价
2014/02/03 职场文书
2014道德模范事迹材料
2014/02/16 职场文书
关于中国梦的演讲稿
2014/04/23 职场文书
机械工程学院大学生求职信
2014/05/25 职场文书
护理专科学生自荐书
2014/07/05 职场文书
2015年派出所工作总结
2015/04/24 职场文书
农村党支部承诺书
2015/04/30 职场文书
python基础学习之递归函数知识总结
2021/05/26 Python
TV动画《间谍过家家》公开PV
2022/03/20 日漫