【问题标题】:Return individual matches not one long match regex返回单个匹配而不是一个长匹配正则表达式
【发布时间】:2019-10-02 07:22:35
【问题描述】:

很确定在 SO 上必须有一个答案,但我的 google fu 让我失望了。

我有一个 js 文件,其中包含一个 javascript 字典数组,开头为:

var a = t.locales = [{
        countryCode: "AF",
        countryName: "Afghanistan"
    }, {
        countryCode: "AL",
        countryName: "Albania"
    },

在返回中没有空格(相对于上面显示的布局),因此带有国家名称的脚本部分将是以下内容的长版本:

[{countryCode:"AF",countryName:"Afghanistan"},{countryCode:"AL",countryName:"Albania"},{countryCode:"DZ",countryName:"Algeria"},{countryCode:"AS",countryName:"American Samoa"},{countryCode:"AD",countryName:"Andorra"},{countryCode:"AO",countryName:"Angola"},{countryCode:"AI",countryName:"Anguilla"},{countryCode:"AG",countryName:"Antigua & Barbuda"},{countryCode:"AR",countryName:"Argentina"},{countryCode:"AM",countryName:"Armenia"},{countryCode:"AW",countryName:"Aruba"},{countryCode:"AU",countryName:"Australia"},{countryCode:"AT",countryName:"Austria"},{countryCode:"AZ",countryName:"Azerbaijan"},{countryCode:"BS",countryName:"Bahamas"},{countryCode:"BH",countryName:"Bahrain"},{countryCode:"BD",countryName:"Bangladesh"},{countryCode:"BB",countryName:"Barbados"},{countryCode:"BY",countryName:"Belarus"},{countryCode:"BE",countryName:"Belgium"},{countryCode:"BZ",countryName:"Belize"},{countryCode:"BJ",countryName:"Benin"},{countryCode:"BM",countryName:"Bermuda"},{countryCode:"BT",countryName:"Bhutan"},{countryCode:"BO",countryName:"Bolivia"},{countryCode:"BQ",countryName:"Bonaire"},{countryCode:"BA",countryName:"Bosnia & Herzegovina"},{countryCode:"BW",countryName:"Botswana"}]

我想用正则表达式输出国家名称,例如'Afghanistan','Albania'......我似乎无法编写正则表达式模式,它会返回一个匹配列表而不是一个大的长匹配。

例如,

countryName:"(.*)"

这会返回一个贪婪的单一匹配,它不是单个国家的列表。

我很欣赏这可能是一件非常简单的事情,但是我尝试过的所有不同的正则表达式都失败了,例如p = re.compile(r'(?<=countryCode:")(.*)[^"]') 。任何人都可以提供适当的正则表达式和解释吗?

注意这是一个特定的我该如何处理正则表达式问题,而不是它是否是适合这项工作的工具。

基本上,我认为我需要在每次国家名称之后的“之前”定义一个模式(例如,而不是在最后一个国家名称之后的“,或者在某些情况下更远)

预期结果是来自该对象的国家/地区列表,例如

['Afghanistan','Albania',.....]

Python:

import re, requests

r = requests.get('https://www.nexmo.com/static/bundle.js')
p = re.compile(r'(?<=countryCode:")(.*)[^"]')     
countries = p.findall(r.text)
print(countries)

【问题讨论】:

  • 为什么不进行非贪婪匹配?
  • 我认为这是我缺乏正则表达式知识。我不确定如何正确地做到这一点。显然 (?
  • 我希望 countryName:"(.*?)" 能够工作。
  • 为什么需要正则表达式?只需解析json。将其分离到不同的文件中,并在需要时将其加载到 python 和 js 中
  • @Sayse 我将不得不使用正则表达式来获取 javascript 对象以加载 json。但是,这个问题特别是关于正则表达式并返回非贪婪的匹配列表,因为我之前遇到过这个问题,或者抓取脚本标签并进行一些字符串处理。这是一个特定的兴趣问题。

标签: python regex python-3.x web-scraping


【解决方案1】:

使用模式r'countryName:\"(.*?)\"'

例如:

import re
data = '[{countryCode:"AF",countryName:"Afghanistan"},{countryCode:"AL",countryName:"Albania"},{countryCode:"DZ",countryName:"Algeria"},{countryCode:"AS",countryName:"American Samoa"},{countryCode:"AD",countryName:"Andorra"},{countryCode:"AO",countryName:"Angola"},{countryCode:"AI",countryName:"Anguilla"},{countryCode:"AG",countryName:"Antigua & Barbuda"},{countryCode:"AR",countryName:"Argentina"},{countryCode:"AM",countryName:"Armenia"},{countryCode:"AW",countryName:"Aruba"},{countryCode:"AU",countryName:"Australia"},{countryCode:"AT",countryName:"Austria"},{countryCode:"AZ",countryName:"Azerbaijan"},{countryCode:"BS",countryName:"Bahamas"},{countryCode:"BH",countryName:"Bahrain"},{countryCode:"BD",countryName:"Bangladesh"},{countryCode:"BB",countryName:"Barbados"},{countryCode:"BY",countryName:"Belarus"},{countryCode:"BE",countryName:"Belgium"},{countryCode:"BZ",countryName:"Belize"},{countryCode:"BJ",countryName:"Benin"},{countryCode:"BM",countryName:"Bermuda"},{countryCode:"BT",countryName:"Bhutan"},{countryCode:"BO",countryName:"Bolivia"},{countryCode:"BQ",countryName:"Bonaire"},{countryCode:"BA",countryName:"Bosnia & Herzegovina"},{countryCode:"BW",countryName:"Botswana"}]'
countries = re.findall(r'countryName:\"(.*?)\"', data)
print(countries)

输出:

['Afghanistan',
 'Albania',
 'Algeria',
 'American Samoa',
 'Andorra',
 'Angola',
 'Anguilla',
 'Antigua & Barbuda',
 'Argentina',
 'Armenia',
 'Aruba',
 'Australia',
 'Austria',
 'Azerbaijan',
 'Bahamas',
 'Bahrain',
 'Bangladesh',
 'Barbados',
 'Belarus',
 'Belgium',
 'Belize',
 'Benin',
 'Bermuda',
 'Bhutan',
 'Bolivia',
 'Bonaire',
 'Bosnia & Herzegovina',
 'Botswana']

【讨论】:

    【解决方案2】:

    您需要更改您的正则表达式以使用(?&lt;=countryName: ")[^"]+ 而不是您当前的。由于您当前使用的是.*,它贪婪地匹配所有内容,因此将匹配所有可能的内容,这就是您的情况。

    试试这些 Python 代码,

    import re
    
    s = '''[{
            countryCode: "AF",
            countryName: "Afghanistan"
        }, {
            countryCode: "AL",
            countryName: "Albania"
        },'''
    
    print(re.findall(r'(?<=countryName: ")[^"]+', s))
    

    打印,

    ['Afghanistan', 'Albania']
    

    【讨论】:

      【解决方案3】:

      使用您的第一个变体的非贪婪版本:

      p = re.compile(r'countryName:"(.*?)"')     
      countries = p.findall(text)
      

      使用像"(.*)" 这样的贪婪匹配的问题是它会匹配到last " 的末尾。

      {countryCode:"AF",countryName:"Afghanistan"},{countryCode:"AL",countryName:"Albania"}
                        ^match  ^ capture start ^ still matches .*      final match of " ^
      

      但是,您希望它以最小匹配结束 - 由非贪婪匹配表示

      {countryCode:"AF",countryName:"Afghanistan"},{countryCode:"AL",countryName:"Albania"}
                        ^match  ^ capture start ^ first match of "
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-14
        • 1970-01-01
        • 1970-01-01
        • 2021-06-17
        • 1970-01-01
        • 1970-01-01
        • 2012-05-27
        相关资源
        最近更新 更多