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
omg21
V2EX  ›  Python

怎样删除部分字符串?

  •  
  •   omg21 · 2016-06-27 19:36:05 +08:00 · 3326 次点击
    这是一个创建于 3072 天前的主题,其中的信息可能已经有所发展或是发生改变。
    <p class="p"><b><span style="font-family: 'Times New Roman'; font-size: 12pt;">一、岗位及人数</span></b><span style="font-family: 'Times New Roman'; font-size: 12pt;"><o:p></o:p></span></p><p class="p"><span style="font-family: 'Times New Roman'; font-size: 12pt;">办公室工作人员,<font face="Times New Roman">1</font><font face="微软雅黑">名;教师,</font><font face="Times New Roman">4</font><font face="微软雅黑">名。</font></span>

    文本是类似这样的,我想删除 tag 里面的 class 、 style ,保留<p><span><div>并且删除掉<font>应该怎么做?
    是用 BS4 还是用字符串操作?
    35 条回复    2016-06-28 23:04:09 +08:00
    15954237961
        1
    15954237961  
       2016-06-27 19:44:09 +08:00
    用 replace 试试
    lslqtz
        2
    lslqtz  
       2016-06-27 19:45:29 +08:00
    正则匹配试试。
    omg21
        3
    omg21  
    OP
       2016-06-27 20:04:03 +08:00
    @15954237961 用 replace 有局限性,这段代码是 class=p ,下段代码有可能就是 class=y 。
    omg21
        4
    omg21  
    OP
       2016-06-27 20:04:37 +08:00
    @lslqtz 用正则容易伤及无辜
    seki
        5
    seki  
       2016-06-27 20:10:38 +08:00
    <font>在这里相当于 <span> 的子元素,所以把文本提出来 append 到 <span> 的文本里面?用 lxml 或者 bs4 ?
    lslqtz
        6
    lslqtz  
       2016-06-27 20:15:47 +08:00
    @omg21 不用代码有局限性。
    lslqtz
        7
    lslqtz  
       2016-06-27 20:15:53 +08:00
    正则 打错。
    lslqtz
        8
    lslqtz  
       2016-06-27 20:20:19 +08:00
    class="(.*?)"
    已提取出来。
    http://233.dog/f_22821044.png
    napsterwu
        9
    napsterwu  
       2016-06-27 20:21:56 +08:00
    js 里面我是这样的
    string.replace(/\s?(class|style)="[^"]+?"/g, '')
    这样可以选择性的删 不过缺点是没有办法清掉 class=""这样的。
    omg21
        10
    omg21  
    OP
       2016-06-27 20:24:14 +08:00
    @seki 我考虑了一下,提<font>的子元素再放到<span>里不好操作啊,搞不清顺序。
    omg21
        11
    omg21  
    OP
       2016-06-27 20:29:36 +08:00
    @lslqtz 嗯,就用这个了
    omg21
        12
    omg21  
    OP
       2016-06-27 20:31:23 +08:00
    @napsterwu 那就在最后单独加个删 class=""的就行了,谢了
    ChiChou
        14
    ChiChou  
       2016-06-27 20:35:47 +08:00
    你可以构建一个 DOM 树然后取 textContent 。。那么 @seki 的方案即可
    Septembers
        15
    Septembers  
       2016-06-27 20:40:49 +08:00
    Septembers
        16
    Septembers  
       2016-06-27 20:43:33 +08:00
    抱歉没看节点请无视
    yxzblue
        17
    yxzblue  
       2016-06-27 20:57:09 +08:00
    ```javascript
    var s = '<p class="p"><b><span style="font-family: \'Times New Roman\'; font-size: 12pt;">一、岗位及人数</span></b><span style="font-family: \'Times New Roman\'; font-size: 12pt;"><o:p></o:p></span></p><p class="p"><span style="font-family: \'Times New Roman\'; font-size: 12pt;">办公室工作人员,<font face="Times New Roman">1</font><font face="微软雅黑">名;教师,</font><font face="Times New Roman">4</font><font face="微软雅黑">名。</font></span>';
    s = s.replace(/(?:\s+(?:class|style)=".+?"|\<font.+?\<\/font\>)/g, '');
    console.log(s);
    ```
    yxzblue
        18
    yxzblue  
       2016-06-27 21:00:26 +08:00
    lslqtz
        19
    lslqtz  
       2016-06-27 21:03:11 +08:00
    人家的方案都挺优雅的。
    quxw
        20
    quxw  
       2016-06-27 21:21:08 +08:00
    一个一个字符遍历,
    '<' '>'之间,不以 'p', '/p' 'span' '/span'开头 的删掉。空格什么再调整下修好了。
    当然前提是你的 html 够规范
    exoticknight
        21
    exoticknight  
       2016-06-27 22:39:45 +08:00
    BS4 ,不用多想
    HTML 规范, BS4 比正则简单,不易错
    HTML 不规范,两个都一样糟糕
    momou
        22
    momou  
       2016-06-28 03:11:27 +08:00
    \s\b(\S*?)[^>]*.*?
    不规范的应该也可以匹配到吧
    Valyrian
        23
    Valyrian  
       2016-06-28 05:23:01 +08:00
    Cabana
        24
    Cabana  
       2016-06-28 09:15:20 +08:00
    对标签属性进行操作肯定用啊 bs ,对于 font 标签,把里面的内容提取出来,放到父节点中
    practicer
        25
    practicer  
       2016-06-28 11:17:14 +08:00
    倾向用正则
    s = '''<p class="p">.......
    .....'''

    >>> pattern = re.compile('\s?(class|style)=\".*?\"\s?')
    >>> result = re.sub(pattern , '', s)
    >>> print result
    davin
        26
    davin  
       2016-06-28 11:19:50 +08:00
    看到了 o:p 标签,这是从 Word 粘贴来的么?
    不知道楼主是用于什么用途,把 Word 导入到 Dreamweaver ,用 Dreamweaver 自带的 「清理 Word 的 HTML 」命令就够了
    yiyiwa
        27
    yiyiwa  
       2016-06-28 15:56:45 +08:00
    刚学啊, 看起来有点恶心,
    #a 就是你的字符串

    >>> print "".join([ "".join(i) for i in re.findall(r'(<[^ >]+>)|>([^<]+)',a) if "font" not in i[0]])
    <b>一、岗位及人数</span></b><o:p></o:p></span></p>办公室工作人员, 1 名;教师, 4 名。</span>
    yiyiwa
        28
    yiyiwa  
       2016-06-28 16:19:49 +08:00
    这样更好点, 正则不熟悉啊

    print "".join([ "".join(i) for i in re.findall("(<(?!/font)[^ >]+>)|>([^<]+)",a)])
    omg21
        29
    omg21  
    OP
       2016-06-28 20:01:06 +08:00
    @practicer 试了一下,你的方案效率最高,能不能解释下这个正则?
    '\s?(class|style)=\".*?\"\s?',或者用空格隔开,我看不懂哪个归哪个。。。
    practicer
        30
    practicer  
       2016-06-28 20:23:58 +08:00
    @omg21 先打开 http://rubular.com/,在这里测效果直观
    是这样的:
    class 和 style 两个属性的匹配规则相同,因此用小括号括起来,再用竖线隔开,表示“或”
    隔开后:
    1. \s?class=\".*?\"\s? 匹配 class 属性
    2. \s?style=\".*?\"\s? 匹配 style 属性
    看细节
    \s 表示空格;
    \s?表示空格匹配零次和一次;
    class=\"表示 class="(反斜杠是转义符);
    .*表示匹配任意字符零次或无限次;

    ?\"表示匹配从左到右第一个双引号,问号指从左到右第一个,不加问好的话会匹配到整个字符串的最后一个双引号,称为贪婪模式,反斜杠仍然是转义符;

    \s?表示匹配空格零次或一次
    ----
    补一下匹配 font 元素字符:<font.+?\/font> 中间的问号同上,匹配从左到右第一个
    omg21
        31
    omg21  
    OP
       2016-06-28 20:36:21 +08:00
    @practicer 太详细了,十分感谢,但是有的情况<p class="p">还有用单引号和不用引号的,这两种情况应该怎么代入?
    omg21
        32
    omg21  
    OP
       2016-06-28 20:58:37 +08:00
    @practicer <p class="p"><p class=‘ p ’><p class=p> 这样三种情况,另外还有双引号里套着单引号的,我是取 class=一直到>之间的内容包括>,然后再用>替换掉。
    >>> pattern = re.compile('\s?(class|style)=.*?>\s?')
    >>> result = re.sub(pattern , '', s)
    已通过,再次感谢。
    practicer
        33
    practicer  
       2016-06-28 21:13:00 +08:00
    @omg21
    s = '''
    <p class="p"><p class=‘ p ’><p class=p>
    '''

    >>> re.compile('<.+?(?=>)', s)
    这样写可以匹配 从左到右第一个 “>” 它前面的所有字符,不管它前面是啥
    omg21
        34
    omg21  
    OP
       2016-06-28 22:31:46 +08:00
    @practicer <p class="p"><td class="p">如何在删除<p>里的 class 的同时保留下来<td class="p">?
    practicer
        35
    practicer  
       2016-06-28 23:04:09 +08:00
    (?<=<p).+?(?=>)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5838 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:57 · PVG 09:57 · LAX 17:57 · JFK 20:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.