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实现简单的遗传算法
Jan 02 Python
Scrapy框架使用的基本知识
Oct 21 Python
浅谈python中真正关闭socket的方法
Dec 18 Python
python贪吃蛇游戏代码
Apr 18 Python
Python简单基础小程序的实例代码
Apr 28 Python
python 实现Flask中返回图片流给前端展示
Jan 09 Python
Tensorflow Summary用法学习笔记
Jan 10 Python
python网络编程之五子棋游戏
May 14 Python
python 下划线的不同用法
Oct 24 Python
Python 如何解决稀疏矩阵运算
May 26 Python
Django rest framework如何自定义用户表
Jun 09 Python
Python干货实战之八音符酱小游戏全过程详解
Oct 24 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
德生PL990,目前市面上唯一一款便携式插卡蓝牙全波段高性能收音机
2021/03/02 无线电
分享一个php 的异常处理程序
2014/06/22 PHP
php截取中文字符串函数实例
2015/02/23 PHP
php实现以只读方式打开文件的方法
2015/03/16 PHP
PHP创建多级目录的两种方法
2016/10/28 PHP
Zend Framework常用校验器详解
2016/12/09 PHP
PHP使用ActiveMQ实现消息队列的方法详解
2019/05/31 PHP
基于JQuery的列表拖动排序实现代码
2013/10/01 Javascript
JS辨别访问浏览器判断是android还是ios系统
2014/08/19 Javascript
jquery实现简单的表单验证
2015/11/17 Javascript
JavaScript实现输入框(密码框)出现提示语
2016/01/12 Javascript
基于JavaScript代码实现自动生成表格
2016/06/15 Javascript
JavaScript获取服务器时间的方法详解
2016/12/11 Javascript
vue2.0中click点击当前li实现动态切换class
2017/06/21 Javascript
为什么我们要做三份 Webpack 配置文件
2017/09/18 Javascript
详解JS中的this、apply、call、bind(经典面试题)
2017/09/19 Javascript
NodeJS实现自定义流的方法
2018/08/01 NodeJs
JavaScript使用表单元素验证表单的示例代码
2019/08/20 Javascript
深入浅析vue全局环境变量和模式
2020/04/28 Javascript
uni-app使用countdown插件实现倒计时
2020/11/01 Javascript
一篇不错的Python入门教程
2007/02/08 Python
python 不关闭控制台的实现方法
2011/10/23 Python
django Layui界面点击弹出对话框并请求逻辑生成分页的动态表格实例
2020/05/12 Python
Python3.8.2安装包及安装教程图文详解(附安装包)
2020/11/28 Python
Python爬虫之App爬虫视频下载的实现
2020/12/08 Python
Needle & Thread官网:英国仙女品牌
2018/01/13 全球购物
英国曼彻斯特宠物用品品牌:Bunty Pet Products
2019/07/27 全球购物
请解释在new与override的区别
2012/10/29 面试题
公务员更新知识培训实施方案
2014/03/31 职场文书
车辆工程专业求职信
2014/06/14 职场文书
学校志愿者活动总结
2014/06/27 职场文书
食品安全汇报材料
2014/08/18 职场文书
在宿舍喝酒的检讨书
2014/09/28 职场文书
招商银行收入证明
2015/06/17 职场文书
JavaScript展开运算符和剩余运算符的区别详解
2022/02/18 Javascript
SQL Server中常用截取字符串函数介绍
2022/03/16 SQL Server