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解析xml模块封装代码
Feb 07 Python
老生常谈python的私有公有属性(必看篇)
Jun 09 Python
Python实现加载及解析properties配置文件的方法
Mar 29 Python
python爱心表白 每天都是浪漫七夕!
Aug 18 Python
python3结合openpyxl库实现excel操作的实例代码
Sep 11 Python
pandas DataFrame 交集并集补集的实现
Jun 24 Python
python如何读取bin文件并下发串口
Jul 05 Python
Python列表删除元素del、pop()和remove()的区别小结
Sep 11 Python
使用Python实现牛顿法求极值
Feb 10 Python
Python 实现敏感目录扫描的示例代码
May 21 Python
django中cookiecutter的使用教程
Dec 03 Python
Python实现滑雪小游戏
Sep 25 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学习笔记 PHP面向对象的程序设计
2011/06/13 PHP
PHP上传图片类显示缩略图功能
2016/06/30 PHP
laravel 解决路由除了根目录其他都404的问题
2019/10/18 PHP
jqGrid jQuery 表格插件测试代码
2011/08/23 Javascript
js multiple全选与取消全选实现代码
2012/12/04 Javascript
jQuery ajax serialize()方法的使用以及常见问题解决
2013/01/27 Javascript
解析ScrollPic在ie8下只滚动一遍,然后变为空白 ie6,ie7,chrome,firefox正常
2013/06/26 Javascript
JavaScript的设计模式经典之建造者模式
2016/02/24 Javascript
jquery精度计算代码 jquery指定精确小数位
2017/02/06 Javascript
Bootstrap中data-target 到底是什么
2017/02/14 Javascript
vue动态组件实现选项卡切换效果
2017/03/08 Javascript
小程序tab页无法传递参数的方法
2018/08/03 Javascript
node实现socket链接与GPRS进行通信的方法
2019/05/20 Javascript
在vue-cli3中使用axios获取本地json操作
2020/07/30 Javascript
jquery自定义组件实例详解
2020/12/31 jQuery
详解Vue2的diff算法
2021/01/06 Vue.js
[01:58]2018DOTA2亚洲邀请赛趣味视频——交流
2018/04/03 DOTA
用smtplib和email封装python发送邮件模块类分享
2014/02/17 Python
在Pycharm中调试Django项目程序的操作方法
2019/07/17 Python
Python OrderedDict的使用案例解析
2019/10/25 Python
pandas数据拼接的实现示例
2020/04/16 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
2021/01/27 Python
Lookfantastic西班牙官网:英国知名美妆购物网站
2018/06/13 全球购物
乌克兰在线电子产品商店:MTA
2019/11/14 全球购物
美国专业消费电子及摄影器材网站:B&H Photo Video
2019/12/18 全球购物
医学专业职业生涯规划范文
2014/02/05 职场文书
法制宣传月活动方案
2014/05/11 职场文书
副乡长群众路线教育实践活动个人对照检查材料
2014/09/19 职场文书
群众路线个人整改方案
2014/10/25 职场文书
综合测评个人总结
2015/03/03 职场文书
2015年派出所民警工作总结
2015/04/24 职场文书
普通员工辞职信范文
2015/05/12 职场文书
师范生见习自我总结
2015/06/23 职场文书
《穷人》教学反思
2016/02/19 职场文书
《游戏公平》教学反思
2016/02/20 职场文书
Redis中一个String类型引发的惨案
2021/07/25 Redis