2016-09-07 3 views
-2

이 제목은 다소 인기가있는 것 같지만, 대개 빠른 사용자 검색은 묻는 사람이 JSON 섹션 하나를 분리 한 상황과 관련이 있습니다.JSON 이스케이프 큰 따옴표

"이 인치를 나타내는 데 사용되거나 이미 큰 따옴표로 묶여있는 JS 개체의 값 문자열에 나타나는 방식으로 닉네임을 나타 내기 위해 문구를 래핑하는 경우가 있습니다. 여기

내가 가진 문제를 가진하고있는 JS 객체 문자열의 예입니다 (내가 열쇠를 인용 더블 여분의 공백을 제거하는 정규식을 작업 한,하지만이 영광의 모든에서 긁어 문자열) :

'{\n\t\t\n\t\t\t\t\t\n\t\n\n\t\n\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"16241885":{title: "Nosefrida Fridababy Windi Gas & Colic Relief", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
\n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"8650356":{title: "Babyganics Face- Hand & Baby Wipes- Fragrance Free- 100 Count", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"16249889":{title: "Nosefrida Nasal Aspirator Replacement Filters", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"8650355":{title: "Babyganics Face- Hand & Baby Wipes- Fragrance Free- 40 Count", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"15490928":{title: "BabyGanics Newborn Ultra Absorbent Jumbo Size Diapers - 36 Count", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"14712536":{title: "Marvel Superhero Bandages", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"16263505":{title: "Nosefrida "The Snotsucker" Nasal Aspirator", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t\t\t, \n\t\t\n\t\n\n\t\t\n\n\t\t \n\n\n\n 
"14848093":{title: "Zarbee\'s Children\'s Cough Syrup - Grape", isIneligible: false, isDiscontinued: false, isLowInventory: false, isAllowed: true} 
    \n\n\t\n\n\t\t\n\t \n\n\t\t\n\t}' 

나는 먼저 문자열에 json.dumps을 시도했지만 그저 두 번 이스케이프하고 double을 필요로한다. json.loads은 나를 다시 정사각형으로 가져온다.

double_quotes_in_json = re.compile(r'(?<=:)(\s*"[^"]*)(")([^"]*)(")?(?=[^"]*",|"\s*\})') 


def escape_double_quotes(jsn_string, pattern=double_quotes_in_json): 
    for match in pattern.finditer(jsn_string): 
     # current pattern only matches 1 instance of either one double quote in JSON value string 
     # (presumably signifying inches) or 1 instance of phrase wrapped in double quotes 
     # for something like nicknames 
     # matches will have either 3 or 4 groups, representing one of the 2 match types described above 
     groups_matched = len(match.groups()) 
     entire_match = match.group() 
     if groups_matched == 3: 
      # we only matched one double quote 
      subbed_match = pattern.sub('$1\\$2$3', entire_match) 
      jsn_string = re.sub(entire_match, subbed_match, jsn_string) 
     elif groups_matched == 4: 
      # we matched a phrase wrapped in double quotes 
      subbed_match = pattern.sub('$1\\$2$3\\$4', entire_match) 
      jsn_string = re.sub(entire_match, subbed_match, jsn_string) 
    return jsn_string 

을 그리고 이것은 가장 유망한 것 같습니다 동안도 첫 번째 그룹에 다시 하도하지는 않지만, 내가 하위에있는 이스케이프 문자없이 큰 따옴표를 다시 삽입 할 것 :이 같은 정규식을 시도 . (I 함께 서브 함수 r에서 원시 문자열 않고 시도) 그래서 상기 문제 섹션 (아래 문자열이다)

"16263505":{title: "Nosefrida "The Snotsucker" Nasal Aspirator" 

패턴과 일부 서브없는 그룹 1 백 수행 이유는 잠깐 인용 부호 (아래는 실패한 정규 표현식 처리의 하위 문자열입니다) :

"16263505":{title: "The Snotsucker"' Nasal Aspirator" 

어느 쪽이든 json.loads은 이스케이프 처리되지 않은 "에 대해 불평합니다.

편집 1 : 정규식을 사용하면 이스케이프 처리되지 않은 따옴표를 꺼낼 수 있지만 원래대로 되돌릴 수는 없습니다. 아마 바보 같은 일을하고 있습니다. 새로운 눈을 사용할 수 있습니다. 인쇄 문 내 기능의

예 출력 :의 re.sub 제대로 따옴표를 탈출하지 않았다 반면 어떤 이유로

low_inventory = response.xpath(
       '//script[contains(., "islistEligibility") or contains(., "ishlistEligibility")]/text()' 
       ).re_first(r'(?s)(?<=registryWislistEligibilityMap)(?:\s*=\s*)(\{.+\})') 

In [453]: for m in double_quotes_in_json.finditer(low_inventory): 
    ...:  groups_matched = len(m.groups()) 
    ...:  print('groups: ', m.groups()) 
    ...:  entire_match = m.group() 
    ...:  print('entire match: ', m.group()) 
    ...:  if groups_matched == 3: 
    ...:    # we only matched a single double quote 
    ...:    subbed_match = double_quotes_in_json.sub(r'$1\\$2$3', entire_match) 
    ...:    print('subbed3: ', subbed_match) 
    ...:    jsn_string = re.sub(entire_match, subbed_match, jsn_string) 
    ...:  elif groups_matched == 4: 
    ...:    subbed_match = double_quotes_in_json.sub(r'$1\\$2$3\\\$4', entire_match) 
    ...:    print('subbed4: ', subbed_match) 
    ...:    jsn_string = re.sub(entire_match, subbed_match, jsn_string) 
    ...: print(jsn_string) 
    ...: 
groups: (' "Nosefrida ', '"', 'The Snotsucker', '"') 
entire match: "Nosefrida "The Snotsucker" 
subbed4: "Nosefrida "The Snotsucker" 
{ "16241885":{"title": "Nosefrida Fridababy Windi Gas &amp; Colic Relief", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "8650356":{"title": "Babyganics Face- Hand &amp; Baby Wipes- Fragrance Free- 100 Count", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "16249889":{"title": "Nosefrida Nasal Aspirator Replacement Filters", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "8650355":{"title": "Babyganics Face- Hand &amp; Baby Wipes- Fragrance Free- 40 Count", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "15490928":{"title": "BabyGanics Newborn Ultra Absorbent Jumbo Size Diapers - 36 Count", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "14712536":{"title": "Marvel Superhero Bandages", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "16263505":{"title": "The Snotsucker"' Nasal Aspirator", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true}, "14848093":{"title": "Zarbee's Children's Cough Syrup - Grape", "isIneligible": false, "isDiscontinued": false, "isLowInventory": false, "isAllowed": true} } 
+3

유효한 JSON이나 Javascript가 아닙니다. 내가 생각할 수있는 언어가 잘못되었습니다. 쓰레기를 분석하려고합니다. 이 쓰레기는 어디서 나옵니까? 소스에서 수정 될 수 있습니까? – deceze

+0

@deceze 스크립트 태그에서 스크랩되었습니다. 무엇이 JS를 무효로 만들까요? –

+1

누구나 스크립트를 실행하려고하면 구문 오류로 인해 스크립트가 중단됩니다. 이것은 확실히 원시 데이터입니까? 임의의''\''가 스크래핑 과정에서 제거 될 수 있습니까? – deceze

답변

0

, 기능을 대체 내장 비단뱀을 사용하여 원하는 결과를 달성했다. (이는 단일 이스케이프가있는 원시 문자열 또는 이중 이스케이프가있는 일반 문자열에서 그룹 참조를 사용하여 수행되었습니다). 어쨌든, 여기에 작동 기능이 있습니다. 누군가가 re.sub를 통해 대체 작업을 사용하는 이유에 대해 약간의 통찰력을 가지고 있다면 나는 이것이 왜 그렇게 중요한지에 관심을 가질 것입니다. (AKA : 잠 접근 후) :

double_quotes_in_json = re.compile(r'(?<=:)(\s*")([^"]*)(")([^"]*)(")?(?=[^"]*",|"\s*\})') 


def escape_double_quotes(jsn_string, pattern=double_quotes_in_json): 
    for match in pattern.finditer(jsn_string): 
     # current pattern only matches 1 instance of either one double quote in JSON value string 
     # (presumably signifying inches) or 1 instance of phrase wrapped in double quotes 
     # for something like nicknames 
     # matches will have either 3 or 4 groups, representing one of the 2 match types described above 
     num_groups_matched = len(match.groups()) 
     groups = match.groups() 
     entire_match = match.group() 
     print('groups: ', match.groups()) 
     print('entire: ', entire_match) 
     if num_groups_matched == 4: 
      # we only matched one double quote 
      # subbed_match = pattern.sub('$1$2\\$3$4', entire_match) 
      # jsn_string = re.sub(entire_match, subbed_match, jsn_string) 
      target = ''.join(groups[1:4]) 
      replaced = target.replace('"', '\\"') 
      print(replaced) 
      jsn_string = jsn_string.replace(target, replaced) 
     elif num_groups_matched == 5: 
      # we matched a phrase wrapped in double quotes 
      # subbed_match = pattern.sub('$1$2\\$3$4\\$5', entire_match) 
      # jsn_string = re.sub(entire_match, subbed_match, jsn_string) 
      target = ''.join(groups[1:]) 
      replaced = target.replace('"', '\\"') 
      print(replaced) 
      jsn_string = jsn_string.replace(target, replaced) 
    return jsn_string 

편집 # 1 (이전 코드는 주석) 도움말 @deceze에 대한

double_quotes_in_title_attr = re.compile(
    r'(?<="title":)(?:\s*")(?P<value>.+?)(?=",\s*"\w+":|"\s*\})' 
) 


def escape_double_quotes_in_title(jsn_string, pattern=double_quotes_in_title_attr): 
    for match in pattern.finditer(jsn_string): 
     target = match.group('value') 
     replaced = target.replace('"', '\\"') 
     jsn_string = jsn_string.replace(target, replaced) 
    return jsn_string 

# use this first to properly quote keys so the above pattern will match 
unquoted_key_pattern = re.compile(r'(?!")(\'?(?P<key>\w+)\'?)(?=:\s*(?:"|false|true|\d|\[|\{))') 

def fix_json_keys(jsn, pattern=unquoted_key_pattern): 
    return pattern.sub(r'"\g<key>"', jsn) 

감사합니다.

관련 문제