zoukankan      html  css  js  c++  java
  • 案例:使用正则表达式的爬虫

    用正则表达式进行对爬取到的全部网页源代码进行筛选。

    网站: https://www.cnblogs.com/loaderman/default.html?page=1

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

    • 第一页url: https://www.cnblogs.com/loaderman/default.html?page=1

    • 第二页url: https://www.cnblogs.com/loaderman/default.html?page=2

    • 第三页url: https://www.cnblogs.com/loaderman/default.html?page=3

    • 第四页url: https://www.cnblogs.com/loaderman/default.html?page=4

    这样我们的url规律找到了,要想爬取所有,只需要修改一个参数即可。 下面我们就开始一步一步将数据爬取下来。


    第一步:获取数据

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

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

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

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

    import urllib2
    
    class Spider:
        """
            爬虫类
        """
        def loadPage(self, page):
            """
                @brief 定义一个url请求网页的方法
                @param page 需要请求的第几页
                @returns 返回的页面html
            """
    
        url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(page)
        #User-Agent头
        user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT
    6.1; Trident/5.0'
    
        headers = {'User-Agent': user_agent}
        req = urllib2.Request(url, headers = headers)
        response = urllib2.urlopen(req)
        html = response.read()
        print html
    
        #return html

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

    • 那么loadPage(self, page) 中的page是我们指定去请求第几页。

    • 最后通过 print html打印到屏幕上。

    • 然后我们写一个main函数见到测试一个loadPage方法

    2. 写main函数测试一个loadPage方法
    if __name__ == '__main__':
        
        print '请按下回车开始'
        raw_input()
    
        #定义一个Spider对象
        mySpider = Spider()
        mySpider.loadpage(1)
    • 程序正常执行的话,我们会在屏幕上打印了第一页的全部html代码。 如果html中的中文部分显示的可能是乱码 。

    则需要简单的将得到的网页源代码处理一下:

    def loadPage(self, page):
        """
            @brief 定义一个url请求网页的方法
            @param page 需要请求的第几页
            @returns 返回的页面html
        """
    
        url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(page)
        #User-Agent头
        user_agent = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT
    6.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')
        # print gbk_html
        return gbk_html

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

    • 这样我们再次执行以下mySpider.py ,会发现之前的中文乱码可以正常显示了。

    第二步:筛选数据

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

    • 首先
    import re
    • 然后, 在我们得到的gbk_html中进行筛选匹配。

    下一步匹配规则:

    打开网页,鼠标点击右键 “ 查看源代码 ” 需要的每个的内容i 描述都是在一个 <div>标签中,而且每个div都有一个属性class = "c_b_p_desc"

    所以,我们只需要匹配到网页中所有<div class="c_b_p_desc"></div> 的数据就可以了。

    根据正则表达式,我们可以推算出一个公式是:
    <div.*?class="c_b_p_desc">(.*?)<a
    • 这个表达式实际上就是匹配到所有divclass="c_b_p_desc 里面的内容(具体可以看正则)

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

          def loadPage(self):
              """
                  作用:下载页面
              """
              print "正在下载数据...."
              url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(self.page)
              headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
              request = urllib2.Request(url, headers = headers)
              response = urllib2.urlopen(request)
      
              # 获取每页的HTML源码字符串
              html = response.read()
              #print html
              # 创建正则表达式规则对象,匹配每页里的内容,re.S 表示匹配全部字符串内容
              pattern = re.compile('<divsclass="c_b_p_desc">(.*?)<a', re.S)
      
              # 将正则匹配对象应用到html源码字符串里,返回
              content_list = pattern.findall(html)
      
              # 调用dealPage() 处理数据里的杂七杂八
              self.dealPage(content_list)
      
          def dealPage(self, content_list):
              """
                  处理每页
      
              """
              for item in content_list:
                  # 将集合里的每个数据按个处理,替换掉无用数据
                  # item = item.replace("<p>","").replace("</p>", "").replace("<br>", "")
                  #print item.decode("gbk")
                  # 处理完后调用writePage() 将写入文件内
                  self.writePage(item)
    • 这里需要注意一个是re.S是正则表达式中匹配的一个参数。

    • 如果 没有re.S 则是 只匹配一行 有没有符合规则的字符串,如果没有则下一行重新匹配。

    • 如果 加上re.S 则是将 所有的字符串 将一个整体进行匹配,findall 将所有匹配到的结果封装到一个list中。
    • 然后我们写了一个遍历item_list的一个方法 printOnePage()
    对于获取的数据可以再次将无用的数据过滤掉,得到我们想要的数据即可

    第三步:保存数据

    • 将数据存放在文件中。
        def writePage(self, item):
            """
                item: 处理后的每条
            """
            # 写入文件内
            print "正在写入数据...."
            with open("loadermanRe.txt", "a") as f:
                f.write(item)

    第四步:显示数据

    • 通过参数的传递对page进行叠加来遍历全部内容。

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

          def startWork(self):
              """
                  控制爬虫运行
              """
              # 循环执行,直到 self.switch == False
              while self.switch:
                  # 用户确定爬取的次数
                  self.loadPage()
                  command = raw_input("如果继续爬取,请按回车(退出输入quit)")
                  if command == "quit":
                      # 如果停止爬取,则输入 quit
                      self.switch = False
                  # 每次循环,page页码自增1
                  self.page += 1
              print "谢谢使用!"
    • 最后,完成后查看当前路径下的loadermanRe.txt文件,里面已经有了我们要的数据。

    简单的小爬虫已实现!!!

    程序整体代码:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import urllib2
    import re
    
    
    class Spider:
        def __init__(self):
            # 初始化起始页位置
            self.page = 1
            # 爬取开关,如果为True继续爬取
            self.switch = True
    
        def loadPage(self):
            """
                作用:下载页面
            """
            print "正在下载数据...."
            url = "https://www.cnblogs.com/loaderman/default.html?page=" + str(self.page)
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
            request = urllib2.Request(url, headers=headers)
            response = urllib2.urlopen(request)
    
            # 获取每页的HTML源码字符串
            html = response.read()
            # print html
            # 创建正则表达式规则对象,匹配每页里的内容,re.S 表示匹配全部字符串内容
            pattern = re.compile('<divsclass="c_b_p_desc">(.*?)<a', re.S)
    
            # 将正则匹配对象应用到html源码字符串里,返回
            content_list = pattern.findall(html)
    
            # 调用dealPage() 处理数据里的杂七杂八
            self.dealPage(content_list)
    
        def dealPage(self, content_list):
            """
                处理每页的数据
    
            """
            for item in content_list:
                # 将集合里按个处理,替换掉无用数据
                # item = item.replace("<p>","").replace("</p>", "").replace("<br>", "")
                # print item.decode("gbk")
                # 处理完后调用writePage() 将写入文件内
                self.writePage(item)
    
        def writePage(self, item):
            """
                item: 处理后的每条
            """
            # 写入文件内
            print "正在写入数据...."
            with open("loadermanRe.txt", "a") as f:
                f.write(item)
    
        def startWork(self):
            """
                控制爬虫运行
            """
            # 循环执行,直到 self.switch == False
            while self.switch:
                # 用户确定爬取的次数
                self.loadPage()
                command = raw_input("如果继续爬取,请按回车(退出输入quit)")
                if command == "quit":
                    # 如果停止爬取,则输入 quit
                    self.switch = False
                # 每次循环,page页码自增1
                self.page += 1
            print "谢谢使用!"
    
    
    if __name__ == "__main__":
        spider = Spider()
        #    spider.loadPage()
        spider.startWork()

    效果:

  • 相关阅读:
    重写JSON的部分用fetch的API
    给网站插入一个百度地图API
    给网站写一个JSON,并远程请求。
    Object的起源及一个函数的标准形式、mechanism分析
    js中关于for 的几个函数及关于构造器或结构体与对象的关系及Arrow functions
    program的发展史及own forecast(后面的才是干货)
    indexof函数分析及其计数字符串函数、正则表达式的例子及分析
    DOM&BOM(source、methods、contents、Application)
    CSS单位分析及CSS颜色表示法、颜色表(调色板)
    一个简单的grid布局基础例子注释及相关分析
  • 原文地址:https://www.cnblogs.com/loaderman/p/11759354.html
Copyright © 2011-2022 走看看