文档章节

python基础 -- 异常处理try的使用及一些思考

明天以后
 明天以后
发布于 2014/11/08 22:21
字数 2047
阅读 1571
收藏 11

    成长的道路上,难免会迷茫,难免会不知所措,能做的就是拥有一个不灭的信念,并一路坚持到底。不要丢掉希望,要坚信,明天会更好。


    算是自己这周工作的小体会吧。第一天新领了公司配的笔记本,然后配置环境。下午以及第二天都是熟悉公司自己根据Scrapy框架稍作封装的框架,然后一步步调试看程序执行顺序。

    第二天下午以及第三天,完成了一个还算简单的爬虫,只是抓取了一个美国的官网。健壮性比较差~~~ 使用xpath抓取时,有些迷茫。原因是网站做的标签有些混乱。或者说是自己经验比较少吧,以后继续补充些这些方面的知识。

    第四天一直到现在,一直在写另外一个爬虫。这个的处理就有些麻烦,因为不只是国内的官网,还有美国,以及欧洲一些国家的官网。其他国家的相对好些,一般变化不大,但是国内的额官网一般都会和其他国家的官网差距比较大。对于单品的抓取,使用的类方法,由于国家的不同,需要传递region参数。然后再根据不同情况进行处理~~~

    其实这两天在抓取的数据,代码已经有现成的了。但是有时官网会改版,这样就会导致xpath无法选取到目的数据,只能重新修改。

    虽然自己水平不高,但是那代码感觉真是没法看啊。稍作修改跑了一下,果然很多数据抓取不到了,然后又细看了一下,好几个地方存在逻辑错误。所以决定重写,按照公司代码比较规范的流程。之前一直在想,代码重要的不就是能正确运行嘛。现在才发现,能运行是程序最基本的东西,其他还有横多重要的部分!

    以下只是其中的一个小部分。需要抓取商品的描述(description)。对应的html代码如下:

<!-- 代码比较多  -->
<!-- http://www.hugoboss.com/uk/extra-slim-fit-jacket-%27ryan_cyl%27-in-a-new-wool-blend/hbeu50275029.html?cgid=21600&dwvar_hbeu50275029_color=410_Dark%20Blue  -->
<html>
 <head></head>
 <body>
  <div class="product-tabs tabs"> 
   <h2 class="visually-hidden">Additional Information</h2> 
   <ul class="tabs-menu clearfix"> 
    <li class="active"> 
     <div class="outerContainer"> 
      <div class="innerContainer"> 
       <div class="element">
        <h2><a href="#tab1">Description</a></h2>
       </div> 
      </div> 
     </div> </li> 
    <li> 
     <div class="outerContainer"> 
      <div class="innerContainer"> 
       <div class="element">
        <h2><a href="#tab2">Details</a></h2>
       </div> 
      </div> 
     </div> </li> 
    <li> 
     <div class="outerContainer"> 
      <div class="innerContainer"> 
       <div class="element">
        <h2><a href="#tab3">Material &amp; care</a></h2>
       </div> 
      </div> 
     </div> </li> 
   </ul> 
   <div style="height: 100px;" id="tab1" class="tab-content active"> 
    <a class="print-page button">Print</a> Sophisticated jacket (extra slim-fit) by BOSS made from a new-wool blend in a plain design. This classic, single-breasted business jacket fits perfectly thanks to the 2 side back vents, 2 waist darts at the front and 3 panel seams at the back. The top-quality finish of its design includes decorative stitching and fine felt at 
    <span style="display: inline;" class="showMore">(Show more…)</span> 
    <span style="display: none;" class="fullText"> the undercollar of the notch lapels, and is an exciting item in the Create your Look series. The classic styling of the 2-button jacket, with 1 breast welt pocket and 2 piped pockets with tucked-down flaps, makes simple and more complex style options possible with a variety of suit trousers or waistcoats. In this way, a totally personal look is created that can be adapted to suit different occasions. </span> 
   </div> 
   <div style="height: 100px;" id="tab2" class="tab-content" itemprop="description"> 
    <a class="print-page button">Print</a> Extra slim fit
    <br />New-wool blend with polyamide and elastane
    <br />Plain design
    <br />2-button jacket, 2 side vents 
    <span class="showMore">(Show more…)</span> 
    <span style="display: none;" class="fullText"> <br />Single-breasted<br />Notch lapel with decorative stitching and fine felt on the undercollar<br />1 breast welt pocket, 2 piped pockets with turned down flaps<br />2 waist darts at the front, 3 panel seams at the back<br />4 kissing buttons on the cuff<br />Back length: 72&nbsp;cm in size&nbsp;48<br />Delivered in a HUGO BOSS garment bag </span> 
   </div> 
   <div style="height: 100px;" id="tab3" class="tab-content"> 
    <div class="material-info-text"> 
     <p class="productinfo-text"> Material information: 85% Virgin wool, 11% Polyamid, 4% Elastane, Lining: 52% Acetate, 48% Viscose, Sleeve lining: 51% Viscose, 49% Acetate </p> 
     <p class="productinfo-text"> Do Not Wash, Iron Low Heat, Do Not Bleach, Reduced Dryclean P, Do Not Tumble Dry </p> 
    </div> 
   </div> 
  </div>
 </body>
</html>

    这里需要抓取 description 和 details 。算了,直接上代码吧。

@classmethod
def fetch_description(cls, response, region=None, spider=None):
    """
    返回单品描述,不同行之间使用'\r'分隔
    由于详细中,存在“打印”以及可能存在的“显示更多”标签。所以将所有文本取出,并替换
    :param response:
    :param spider:
    :return:
    """
    sel = Selector(response)
    description = None
    if region == 'cn':
        description_node = sel.xpath('//div[@id="lyr1"][contains(@class,"description")]')
    else:
        description_node = sel.xpath('//div[contains(@class, "product-detail")]//div[@id="tab1"]')
    if description_node:
        try:
            description = '\r'.join(cls.reformat(val) for val in description_node.xpath('.//text()').extract())
            print_node = description_node.xpath('.//*[contains(@class, "print-page")]/text()').extract()[0]
            if print_node:
                print_node = cls.reformat(print_node)
                description = description.replace(print_node, '')
            show_more_node = description_node.xpath('.//*[contains(@class, "showMore")]/text()').extract()[0]
            if show_more_node:
                show_more_node = cls.reformat(show_more_node)
                description = description.replace(show_more_node, '')
        except(TypeError, IndexError):
            pass
    description = cls.reformat(description)
    return description

    不难看到,其实代码还是挺简单的。只是最开始写代码的时候,考虑不全面,bug到处都是。然后再一步步调试,看自己的代码是否像预期那样执行。

    程序大体执行:先判断国家,根据国家的不同,xpath结点的选取有所不同。当结点存在时,继续向下执行,由于xpath.extract() 返回的是一个列表,所以要取值时,需要使用到列表的切片选取第一个元素。但是列表可能为空列表,对空列表执行[0]操作时,会报 IndexError 错误。所以使用 try ... except ...  来捕获异常,此时出现的异常不需要处理,直接向下执行就行。问题的关键就在  try... 下面的代码块中。之前的代码修改了三次,现在才正常。最早的代码如下:

    if description_node:
        try:
            print_node = description_node.xpath('.//*[contains(@class, "print-page")]/text()').extract()[0]
            show_more_node = description_node.xpath('.//*[contains(@class, "showMore")]/text()').extract()[0]
            description = '\r'.join(cls.reformat(val) for val in description_node.xpath('.//text()').extract())
            if print_node:
                print_node = cls.reformat(print_node)
                description = description.replace(print_node, '')
            if show_more_node:
                show_more_node = cls.reformat(show_more_node)
                description = description.replace(show_more_node, '')
        except(TypeError, IndexError):
            pass

    不难发现,这段代码存在严重的问题。当执行到 try 代码块中,说明存在 描述结点的。

    但此时,如果 print_node 或 show_more_node 的xpath 返回空值时,他们就是空列表,程序便终止执行 try 中剩下的代码,直接进入 except 异常处理块中。修改完如下:

    if description_node:
        try:
            description = '\r'.join(cls.reformat(val) for val in description_node.xpath('.//text()').extract())
            print_node = description_node.xpath('.//*[contains(@class, "print-page")]/text()').extract()[0]
            show_more_node = description_node.xpath('.//*[contains(@class, "showMore")]/text()').extract()[0]
            if print_node:
                print_node = cls.reformat(print_node)
                description = description.replace(print_node, '')
            if show_more_node:
                show_more_node = cls.reformat(show_more_node)
                description = description.replace(show_more_node, '')
        except(TypeError, IndexError):
            pass

    此时如果html中存在 description,就一定能抓取到。但是代码中存在 ‘打印’和 可能存在 ‘显示更多’。通过执行发现‘打印’二字,时而出现时而消失。当时感觉挺奇怪的,然后又一想,可能是html代码有些变化,导致xpath提取不出来 print_node 。但是使用 scrapt shell url ,调试时发现可以取到 ‘打印’的。然后又单步调试,发现,执行到 show_more_node 后,直接就进入了 except 代码段。恍然明白,这段描述没有‘显示更多’,剩下的替换代码,没有执行。然后又修改代码:

    if description_node:
        try:
            description = '\r'.join(cls.reformat(val) for val in description_node.xpath('.//text()').extract())
            print_node = description_node.xpath('.//*[contains(@class, "print-page")]/text()').extract()[0]
            if print_node:
                print_node = cls.reformat(print_node)
                description = description.replace(print_node, '')
            show_more_node = description_node.xpath('.//*[contains(@class, "showMore")]/text()').extract()[0]
            if show_more_node:
                show_more_node = cls.reformat(show_more_node)
                description = description.replace(show_more_node, '')
        except(TypeError, IndexError):
            pass

    此时代码完全正常了。

    还需要注意的一点就是 try 中代码的顺序。因为这段最主要的目的就是抓取 description ,如果存在的话, ‘打印’结点可能存在,‘显示更多’也可能存在,但是‘打印’一定出现在‘显示更多’前面,所以顺序需要时:  description -> print_node -> show_more_node 

    当然这也跟代码的书写有些关系。如果使用  if 来判断抓取返回的列表是否为空,就不用再使用 try 异常处理了。


    像是个寓言小故事,最后的结论就是:

# 在使用
try:
    pass
    # 一定要注意这里面语句的顺序
    # 一旦出现异常,代码就会终止执行本块剩下的代码
except:
    pass

# 所以 try 的使用,一定要谨慎
# ‘知道’ --》 ‘体会到’ 还是有一点距离的

    一直在纠结,是谨慎使用,还是使用谨慎。好像都对,又好像都不太确切~ 哈哈~~~

© 著作权归作者所有

共有 人打赏支持
明天以后
粉丝 71
博文 124
码字总数 82816
作品 0
昌平
程序员
加载中

评论(5)

明天以后
明天以后

引用来自“DreamThere”的评论

你是做前段?
人不知而不愠,不亦君子乎 ~
tube
tube
Python博客,Python教程。Python,Django,Flask,Uliweb在线中文文档。http://www.xuyukun.com
明天以后
明天以后

引用来自“呢喃的猫咪”的评论

学习了,我也在学习Python
给你推荐个好地方,一些常用的框架模块等~ Awesome Python https://github.com/vinta/awesome-python#awesome-python
呢喃的猫咪
呢喃的猫咪
学习了,我也在学习Python
DreamThere
DreamThere
你是做前段?
【第十章】python之异常处理篇

异常,顾名思义,属于不正常情况,但并不代表报错。 今天和大家一起学习的是python的异常处理,捕获异常也是程序经常用到的地方,直接通过下面案例来了解: 运行结果: python的异常,使用的...

你好夜故事
08/14
0
0
Python入门教程系列:一、异常处理

前面几章,我们已经把Python的基础内容简单说了一些,从这章开始,我们算是入门级别的学习了,主要把剩下的一些内容说一下,主要包括异常处理、模块的使用、函数的使用、面向对象、正则匹配、...

东方神剑
2015/02/14
0
0
搞清楚 Python traceback

上周公司组织Python方面的代码review,其中提到一个问题就是没有一个统一的异常日志分析机制,都乱七八糟的,然后回头看了一下自己项目的异常处理方面,感觉对Python异常体系以及相关的工具模...

张旭0512
2015/01/05
0
0
经典7大Python面试题!看完考官竟然给了我50k的薪资

  Python面试(一)之交换变量值   平时时不时会面面实习生,大多数的同学在学校里都已经掌握了Python。面试的时候要求同学们实现一个简单的函数,交换两个变量的值,大多数的同学给出的...

菜鸟学Python
08/07
0
0
经典7大Python面试题!看完考官竟然给了我30k的薪资

Python面试(一)之交换变量值 平时时不时会面面实习生,大多数的同学在学校里都已经掌握了Python。面试的时候要求同学们实现一个简单的函数,交换两个变量的值,大多数的同学给出的都是如下...

燕大侠V
08/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

c语言之内存分配笔记

先看一个数组: short array[5] = {1,2} // 这儿定义的一个int类型的数组,数组第1和第2个元素值是1和2.其余后面默认会给值为0; 或者 short array[] = {1,2};//这儿数组第1和第2个元素,数组...

DannyCoder
今天
2
0
Shell | linux安装包不用选择Y/N的方法

apt-get install -y packageOR echo "y" | sudo apt-get install package

云迹
今天
2
0
Hadoop的大数据生态圈

基于Hadoop的大数据的产品圈 大数据产品的一句话概括 Apache Hadoop: 是Apache开源组织的一个分布式计算开源框架,提供了一个分布式文件系统子项目(HDFS)和支持MapReduce分布式计算的软件架...

zimingforever
今天
5
0
八大包装类型的equals方法

先看其中一个源码 结论:八大包装类型的equals方法都是先判断类型是否相同,不相同则是false,相同则判断值是否相等 注意:包装类型不能直接用==来等值比较,否则编译报错,但是数值的基本类型...

xuklc
今天
2
0
NoSQL , Memcached介绍

什么是NoSQL 非关系型数据库就是NoSQL,关系型数据库代表MySQL 对于关系型数据库来说,是需要把数据存储到库、表、行、字段里,查询的时候根据条件一行一行地去匹配,当量非常大的时候就很耗...

TaoXu
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部