簡體   English   中英

更好的方式使用re.sub

[英]Better way to use re.sub

我正在通過推特流清理一系列來源。 以下是數據示例:

source = ['<a href="https://twitter.com/download/android" rel="nofollow">Twitter for Android Tablets</a>', 
          '<a href="https://twitter.com/download/android" rel="nofollow">Twitter for  Android</a>',
          '<a href="http://foursquare.com" rel="nofollow">foursquare</a>', 'web',
          '<a href="http://twitter.com/download/iphone" rel="nofollow">Twitter for iPhone</a>',
          '<a href="http://blackberry.com/twitter" rel="nofollow">Twitter for BlackBerry</a>']


import re
for i in source:
    re.sub('<.*?>', '', re.sub(r'(<.*?>)(Twitter for)(\s+)', r'', i))

### This would be the expected output ###
'Android Tablets'
'Android'
'foursquare'
'web'
'iPhone'
'BlackBerry'

后者是我完成工作的代碼,但看起來很糟糕。 我希望有更好的方法來做到這一點,包括re.sub()或其他可能更適合的功能。

另一種選擇,使用BeautifulSoup html解析器:

>>> from bs4 import BeautifulSoup
>>> for link in source:
...     print BeautifulSoup(link, 'html.parser').text.replace('Twitter for', '').strip()
... 
Android Tablets
Android
foursquare
web
iPhone
BlackBerry

如果您正在執行大量這些操作,請使用旨在處理(X)HTML的庫。 lxml運行良好,但我對BeautifulSoup包裝器更熟悉。

from bs4 import BeautifulSoup

source = ['<a href="https://twitter.com/download/android" rel="nofollow">Twitter for Android Tablets</a>', 
      '<a href="https://twitter.com/download/android" rel="nofollow">Twitter for  Android</a>',
      '<a href="http://foursquare.com" rel="nofollow">foursquare</a>', 'web',
      '<a href="http://twitter.com/download/iphone" rel="nofollow">Twitter for iPhone</a>',
      '<a href="http://blackberry.com/twitter" rel="nofollow">Twitter for BlackBerry</a>']

soup = BeautifulSoup('\n'.join(source))
for tag in soup.findAll('a'):
    print(tag.text)

但是,對於您的用例,這可能有點過分。

以下是改進代碼的建議:

  • 使用正則表達式編譯,這樣每次應用正則表達式時都不會處理正則表達式,
  • 使用原始字符串來避免python對正則表達式字符串的任何解釋,
  • 使用一個正則表達式,除了結束標記字符之外,它只需要在標記內進行匹配
  • 您不需要重復替換,因為它匹配默認情況下每行的出現次數

這是一個更簡單,更好的結果:

>>> import re
>>> r = re.compile(r'<[^>]+>')
>>> for it in source:
...     r.sub('', it)
... 
'Twitter for Android Tablets'
'Twitter for  Android'
'foursquare'
'web'
'Twitter for iPhone'
'Twitter for BlackBerry'

注意:對你的用例最好的解決方案是@ bakuriu的建議:

 >>> for it in source:
 ...     it[it.index('>')+1:it.rindex('<')]
'Twitter for Android Tablets'
'Twitter for  Android'
'foursquare'
'Twitter for iPhone'
'Twitter for BlackBerry'

這不會增加重要的開銷,並使用基本的快速字符串操作。 但是,該解決方案采用標簽之間的內容 ,而不是刪除標簽,如果<a></a>有標簽或根本沒有標簽,則可能會產生副作用,即它不適用於web字符串。 根本沒有標簽的解決方案:

 >>> for it in source:
 ...     if '>' in it and '<' in it:
 ...         it[it.index('>')+1:it.rindex('<')]
 ...     else:
 ...         it
 'Twitter for Android Tablets'
 'Twitter for  Android'
 'foursquare'
 'web'
 'Twitter for iPhone'
 'Twitter for BlackBerry'

一個選項,如果文本真的是這種格式的一致性,只是使用字符串操作而不是正則表達式:

source = ['<a href="https://twitter.com/download/android" rel="nofollow">Twitter for Android Tablets</a>', 
          '<a href="https://twitter.com/download/android" rel="nofollow">Twitter for  Android</a>',
          '<a href="http://foursquare.com" rel="nofollow">foursquare</a>', 'web',
          '<a href="http://twitter.com/download/iphone" rel="nofollow">Twitter for iPhone</a>',
          '<a href="http://blackberry.com/twitter" rel="nofollow">Twitter for BlackBerry</a>']

for i in source:
    print i.partition('>')[-1].rpartition('<')[0]

這段代碼在字符串中找到第一個'>',取出后面的所有內容,在剩下的內容中找到第一個'<',並在此之前返回所有內容; 例如,在第一個'>'和最后一個'<'之間給你任何文字。

還有更多最小版本@Bakuriu發表評論,這可能比我的更好!

這看起來不那么難看,應該同樣有效:

import re
for i in source:
    print re.sub('(<.*?>)|(Twitter for\s+)', '', i);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM