Zonor
@Zonor
Начинающий веб программист

Как распарсить массив возвращаемый сервером в виде обычной строки?

Есть задача, пока не ясно куда копать, так не хочется использовать регулярки, но пока другого решения не вижу, можно сделать как на php так и на Python. Второй я только начал изучать.
Вообщем на странице подгружаются данные по запросу на JS скрипт, запрос отловил, отправляю его сам - приходит ответ в виде строки обычной, не json. Такого вида:
"var A=Array(376);
var B=Array(135);
var C=Array(66);
A[1]=[1765540,14,2799,4790,'Ts','MSC','2019,8,7,21,00,00',-1,3,2,1,2,1,1,1,2,'20','13','','',82,'','',8,0];A[2]=[1706041,83,4134,19230,'3DF','rSC','2019,8,7,21,00,00',-1,3,1,2,0,0,0,0,0,'14','8','','',66,'','',0,0];
..."
и так далее. Проблема сама в том что это String а не JSON и такую строку надо как то превратить в массив... Нужно достать массив A и распарсить его в массив PHP/Python. Кроме регулярок пока решения не могу увидеть или загуглить, так как видимо задача какая то редкая. Но так не хочется заморачиваться регулярками, т.к. массив большой всегда отдается от 200 до 1000 значений, мало ли где будет точка с запятой что неправильно разобьет строку или еще какая заковырка.
P.S. Поправил вопрос дабы некоторые не путались с тегом code. Хотел выделить чтобы было понятно но получилось как всегда...
  • Вопрос задан
  • 797 просмотров
Решения вопроса 2
adugin
@adugin Куратор тега Python
import re
import pandas as pd
from io import StringIO

srv_data = "A[1]=[1765540,14,2799,4790,'Ts','MSC','2019,8,7,21,00,00',-1,3,2,1,2,1,1,1,2,'20','13','','',82,'','',8,0];"\
           "A[2]=[1706041,83,4134,19230,'3DF','rSC','2019,8,7,21,00,00',-1,3,1,2,0,0,0,0,0,'14','8','','',66,'','',0,0];"

csv_data = '\n'.join(re.findall('=\[(.+?)\];', srv_data))

# Вариант без регулярок:
# csv_data = '\n'.join(line.split('=')[1].strip('[]') for line in srv_data.split(';') if line)

df = pd.read_csv(StringIO(csv_data), quotechar="'", header=None)

5d8606aaad01d242226827.png

Самый лаконичный вариант, но строго не рекомендуется ввиду риска запуска переданного кода:
import pandas as pd

data = "A[1]=[1765540,14,2799,4790,'Ts','MSC','2019,8,7,21,00,00',-1,3,2,1,2,1,1,1,2,'20','13','','',82,'','',8,0];"\
       "A[2]=[1706041,83,4134,19230,'3DF','rSC','2019,8,7,21,00,00',-1,3,1,2,0,0,0,0,0,'14','8','','',66,'','',0,0];"

A = {}
exec(data)  # Потенциально опасная операция, т.к. в ответе сервера может быть вредоносный код

pd.DataFrame(A.values())

5d85ffb1038ac596871535.png

Если не хотите связываться с Pandas, можно применить namedtuple.
Ответ написан
@bbkmzzzz
без без регулярок и pandas
Текст структурирован, так что вот:
stroke = "A[1]=[1765540,14,2799,4790,'Ts','MSC','2019,8,7,21,00,00',-1,3,2,1,2,1,1,1,2,'20','13','','',82,'','',8,0];A[2]=[1706041,83,4134,19230,'3DF','rSC','2019,8,7,21,00,00',-1,3,1,2,0,0,0,0,0,'14','8','','',66,'','',0,0];"
list_of_arrays = stroke.split(';') #  делим записи по ;

for i in list_of_arrays:
  # если вдруг пустой элемент списка
  if not i: 
    continue
  # делим каждую запись на 2 части, A[1] и все остальное
  head, body = i.split('=')
  
  # вторая часть, удаляем символы [], и сразу делим на элементы по ,
  body = body.replace('[', '').replace(']', '').split(',')
  
  # проходим по всем элементам тела
  for num, val in enumerate(body):
    # удаляем символы '
    body[num] = val.replace("'", '')
    try:
      # пробуем привести к числу
      body[num] = int(body[num])
    except ValueError:
      # значит строка
      pass
  
  # делим A[1] по символу [, берем вторую часть и удаляем там ]
  head_number = head.split('[')[1].replace(']', '')
  
  
  head = head.split('[')[0]
  print(f'head: {head}\nhead_num: {head_number}\nbody:{body}\n')

есть допущения.
1. Всегда имеется индекс у заголовка: A[1]
2. Числа всегда целые. С плавающей точкой приведутся к целому
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
FanatPHP
@FanatPHP
Чебуратор тега РНР
Непонятна боязнь автора перед регулярками.
Как будто любой другой парсер не споткнется о пропущенную точку с запятой.
При том что регулярки делают код на порядки короче.

preg_match_all('!A\[\d+\]=\[(.*?)\]!', $s, $matches);
$data = [];
foreach ($matches[1] as $row) {
    $data[] = str_getcsv($row, ",", "'");
}


ЗЫ.
Мне не верится, что в питоне все настолько плохо.
Хотелось бы увидеть решение от человека знающего язык.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы