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中的元组概念
May 21 Python
Python3读取zip文件信息的方法
May 22 Python
Python File readlines() 使用方法
Mar 19 Python
Python实现基于POS算法的区块链
Aug 07 Python
python3 深浅copy对比详解
Aug 12 Python
Django项目创建到启动详解(最全最详细)
Sep 07 Python
Python实现字符串中某个字母的替代功能
Oct 21 Python
Python3.9又更新了:dict内置新功能
Feb 28 Python
python 实现 hive中类似 lateral view explode的功能示例
May 18 Python
Python是什么 Python的用处
May 26 Python
Python内置方法和属性应用:反射和单例(推荐)
Jun 19 Python
基于Python和openCV实现图像的全景拼接详细步骤
Oct 05 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和ACCESS写聊天室(八)
2006/10/09 PHP
php 随机记录mysql rand()造成CPU 100%的解决办法
2010/05/18 PHP
PHP关联数组的10个操作技巧
2013/01/21 PHP
PHP中开启gzip压缩的2种方法
2015/01/31 PHP
php源码分析之DZX1.5加密解密函数authcode用法
2015/06/17 PHP
PHP全功能无变形图片裁剪操作类与用法示例
2017/01/10 PHP
extJs 常用到的增,删,改,查操作代码
2009/12/28 Javascript
jquery事件机制扩展插件 jquery鼠标右键事件
2011/12/21 Javascript
原始的js代码和jquery对比体会
2013/09/10 Javascript
全面解析Bootstrap中tooltip、popover的使用方法
2016/06/13 Javascript
如何用JS判断两个数字的大小
2016/07/21 Javascript
jquery+Jscex打造游戏力度条
2020/09/12 Javascript
Html5 js实现手风琴效果
2020/04/17 Javascript
nodejs开发——express路由与中间件
2017/03/24 NodeJs
AngularJs定时器$interval 和 $timeout详解
2017/05/25 Javascript
vue写一个组件
2018/04/09 Javascript
vue 实现数字滚动增加效果的实例代码
2018/07/06 Javascript
vue 实现锚点功能操作
2020/08/10 Javascript
nodejs中的异步编程知识点详解
2021/01/17 NodeJs
Python sys.path详细介绍
2013/10/17 Python
Python实现FM算法解析
2019/06/18 Python
Python tkinter实现图片标注功能(完整代码)
2019/12/08 Python
自定义Django_rest_framework_jwt登陆错误返回的解决
2020/10/18 Python
Python实现壁纸下载与轮换
2020/10/19 Python
python常量折叠基础知识点讲解
2021/02/28 Python
IE10 Error.stack 让脚本调试更加方便快捷
2013/04/22 HTML / CSS
Harrods英国:世界领先的奢侈品百货商店
2020/09/23 全球购物
经济信息管理专业大学生求职信
2013/09/27 职场文书
大学生四年生活自我鉴定
2013/11/21 职场文书
教师自我鉴定范文
2014/03/20 职场文书
反洗钱宣传活动总结
2014/08/26 职场文书
纪念九一八爱国演讲稿600字
2014/09/14 职场文书
领导班子四风对照检查材料
2014/09/23 职场文书
硕士学位论文评语
2014/12/31 职场文书
干部作风纪律整顿心得体会
2016/01/23 职场文书
开学第一周日记(三篇范文)
2019/08/23 职场文书