V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
chunhai
V2EX  ›  Python

Python 循环其中一行代码异常如何继续执行后续代码?而不是跳过当前循环

  •  
  •   chunhai · 132 天前 · 1606 次点击
    这是一个创建于 132 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在 for 循环中一行代码抛出异常,接着执行下一行代码如何实现?而不是跳过本次循环

    我写的一个爬虫,读取书籍的信息,有的书只有部分数据有,所以造成有的对象不存在而出错。 我也想过在赋值之前先判断,但是感觉有点麻烦,想找找别的写法。 下面的代码中,如果 pubulisher 读取出错,那么后面的 author 他也不会读了直接跳下一个循环了

    for i in rows:
        
        try:
            book = {}
            tmp = i.find("h3", {"itemprop": "name"})
            book['title'] = tmp.text.strip()
            book['cover'] = i.find("img")['data-src']
            book['url'] = lib_url+tmp.a['href']
            book['publisher'] = i.find("a", {"title": "Publisher"}).text.strip()
            book['author'] = i.find("a", {"itemprop": "author"}).text.strip()
            detail = i.find("div", {"class": "bookDetailsBox"})
            book['year'] = detail.find("div", {"class": "property_year"}).find(
                "div", {"class": "property_value"}).text
            book['language'] = detail.find("div", {"class": "text-capitalize"}).text
        except AttributeError:
            pass
        print(book)
    
    
    11 条回复    2022-09-22 21:51:52 +08:00
    dorothyREN
        1
    dorothyREN  
       132 天前
    一行一个 try
    chunhai
        2
    chunhai  
    OP
       132 天前
    @dorothyREN 不够 pythonic 啊
    dorothyREN
        3
    dorothyREN  
       132 天前
    @chunhai #2 pythonic 又不能当饭吃
    shinonome
        4
    shinonome  
       132 天前
    我的能力范围内就是会出错的地方就 try
    ClericPy
        5
    ClericPy  
       132 天前   ❤️ 1
    1. 把安全字段放前面啊
    2. 不好看你包个函数起码就好看了, 比如 find 方法给它装饰器魔改一下传回个默认值( Null 对象模式 )
    3. 直接改面向对象, 不安全的对象里 catch 住
    4. 如果是工作中遇到的, 不要过早优化, 如果是写着玩就无所谓了, 多看看 Cookbook 和 Fluent Python 吧
    secondwtq
        6
    secondwtq  
       132 天前
    试试 On Error Resume Next
    filwaline
        7
    filwaline  
       132 天前   ❤️ 1
    每一个数据查询都要单独处理不存在的情况,而不是摆在一起等异常抛出。

    比如 `language`:
    ``
    language_result = detail.find("div", {"class": "text-caplitalize"})
    book["language"] = language_result and language_result.text
    ``

    借助短路逻辑,判断 language 有没有查询到,在有的前提下才取出 text 属性,否则自然就得到了 None ,而不是抛出错误。
    krixaar
        8
    krixaar  
       132 天前
    因为要的全都是 text ,就不要 tmp 和 detail 了,全部都改成 i.find(),因为 soup.find 找不到的时候返回 None ,这样,第一轮执行下来 book 的值要么是 None 要么是找到的 tag ,最后只要一行 dictionary comprehension ,对非 None 的取 text ,就拿到了所有的 text ,再对 url 单独处理一下。
    如果 i 有可能 None ,那就在最前面加 guard clause ,i 不能.find 的时候 continue 。
    这样基本上就不用 try 了。
    LindsayZhou
        9
    LindsayZhou  
       131 天前
    那就不抛错误。
    这样?
    ``` python
    book['publisher'] = getattr(
    i.find("a", {"title": "Publisher"}),
    'text',
    '').strip()
    ```
    LindsayZhou
        10
    LindsayZhou  
       131 天前
    想到还可以用海象表达式这么玩:
    ``` python
    book['publisher'] = '' if (y:=i.find("a", {"title": "Publisher"})) is None else y.text.strip()
    ```
    fbichijing
        11
    fbichijing  
       131 天前
    def format_text(obj):
    if not obj:
    return None
    return obj.text.strip()

    直接搞个函数套上就行了。用 find 应该是 BeautifulSoup 的,find 本身找不到表达式会返回 None ,所以出问题的部分是你获取数值时没有考虑空的情况造成的异常。

    如果我自己在写可能会考虑这种方式,感觉方便但是没有点语法雅观。但相比去改变模块里面的数据格式,可能这种来得更简单直接一些。印象中以前写 xpath 时就是这么弄的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   3579 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 45ms · UTC 06:40 · PVG 14:40 · LAX 22:40 · JFK 01:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.