Таблица в массив на php

Задача: Есть некая очень захламленная сторонними элементами страница в разметке html. Необходимо преобразовать находящуюся на ней таблица в массив данных.

Решение: сначала вычленим «грязное» содержимое таблицы между тегами <tbody></tbody>, затем преобразуем его в DOM документ, а далее уже распарсим его обходами и разложим элементы в массив.

Получилось что-то вроде:

 //вычленяю таблицу
        $t1=explode("<tbody>",$res);
        $t2=explode("</tbody>",$t1[1]);
        $tbody="<html><head><meta charset='UTF-8'></head><body><table><tbody>".$t2[0]."</tbody></table></body></html>";
        
        $mass=[];
        $dom = new domDocument('1.0', 'utf-8'); 
        @$dom->loadHTML($tbody);         
        $tables= $dom->getElementsByTagName('table');
        foreach ($tables as $table) {
            $trs= $table->getElementsByTagName('tr');
            foreach ($trs as $tr) {
                $tds=$tr->getElementsByTagName('td');
                $info=[];
                foreach ($tds as $td) {                    
                    $info[]=$td->textContent;
                };
                $mass[]=$info;
            }
        }        

Bitrix: Request is not XHR

В одном из проектов, скрипт парсит сайт на bitrix. С какого то момента, при установке параметров таблицы отдаваемой по ajax, стала выводиться ошибка «Request is not XHR». Быстрый гуглинг решения не дал. Стал кропотливо сравнивать заголовки которые отдаются запросом в браузере и заголовки который отдавал в скрипте. Отличие нашлось относительно быстро, страница на сайте добавляла дополнительный заголовок «Bx-ajax:true». В результате модифицировал скрипт следующим образом:

        $custom_header=[];
        $custom_header[]="Access-Control-Allow-Origin: *";
        $custom_header[]="Accept: */*";
        $custom_header[]="Bx-ajax:true";
        $res=$this->request("/bitrix/components/bitrix/main.ui.grid/settings.ajax.php?GRID_ID=".$grid_id."&bxajaxid=".$bxajaxid."&action=setSort",$param,"POST",true,$custom_header);        
        var_dump($res);

Сама функция запроса уже устоялась, и при таскании из скрипта в скрипт у меня выглядит так::

 public function request($query,$param,$type="POST",$headers=false,$custom_header=[],$follow_location=true) {
        $url=$this->url.$query;
        if ($this->debug==true){echo "URL:$url\n";};
        $ch = curl_init($url);        
        curl_setopt($ch, CURLOPT_VERBOSE, $this->debug);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $follow_location); 
        if ($headers==true){
            curl_setopt($ch, CURLOPT_HEADER, 1);
        };
        if ($type=="POST"){
            curl_setopt($ch, CURLOPT_POST, 1);        
            curl_setopt($ch, CURLOPT_POSTFIELDS, $param);
            if ($this->debug==true){
                echo "---------------- POST -------------\n";
                var_dump($param);
                echo "-----------------------------------\n";
            };
        };        
        if (count($custom_header)>0){          
          curl_setopt($ch, CURLOPT_HTTPHEADER, $custom_header);  
          if ($this->debug==true){
            echo "---------------- HEADER -------------\n";            
            var_dump($custom_header);
            echo "-----------------------------------\n";
          };
        };
        if (count($this->cookies)>0){
            $str_cook="";
            foreach ($this->cookies as $key=>$value) {
             $str_cook=$str_cook.$key."=".$value.";";   
            };
            if ($this->debug==true){
                echo "COOKIE:$str_cook\n";  
            };

            curl_setopt($ch, CURLOPT_COOKIE,$str_cook);               
        };
        
        $res=curl_exec($ch);        
          if (curl_errno($ch)) {
            $error_msg = curl_error($ch);
            if ($this->debug==true){
              var_dump($res);
              var_dump($error_msg);
              die();  
            };
          };  
        if ($this->debug==true){
                echo "---------------- РЕЗУЛЬТАТ -------------\n";
                var_dump($res);
                echo "-------------------------- -------------\n";
        };          
        return $res;
    }    
Request is not XHR

Работа с безопасным хранилищем в 1С

До недавнего времени (еще несколько лет назад) для хранения данных учётных записей в 1С единственной защитой было — показывать поле с паролем со «звездочками». Сам же пароль хранился в практически открытом виде в реквизитах формы. Ну.. возможно это и не безопасно.. Новая методика хранения чувствительных данных в 1С призвана эту безопасность увеличить. Работа с безопасным хранилищем в 1с, Поэтому в БСП были внедрены функции общего назначения «ПрочитатьДанныеИзБезопасногоХранилища» и «ЗаписатьДанныеВБезопасноеХранилище».

Например запишу данные:

       УстановитьПривилегированныйРежим(Истина);
       ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище(ТекущийОбъект.Ссылка, Пароль,"ПарольSMTP");
       УстановитьПривилегированныйРежим(Ложь);

Прочитаю данные:

	 УстановитьПривилегированныйРежим(Истина);
	  уз=справочники.УчетныеЗаписиЭлектроннойПочты.НайтиПоНаименованию("Учетка для чтения писем");
      Пароли = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(уз, "Пароль, ПарольSMTP");
	УстановитьПривилегированныйРежим(Ложь);	  		

В чём разница между хранением в реквизитах и новой методикой:

  • Имея доступ к объекту метаданных, пользователь может прочитать содержимое реквизита с паролем, что невозможно при использовании безопасного хранилища. Для исключения случаев несанкционированного доступа к безопасному хранилищу получение и запись данных (паролей) возможна только в привилегированном режиме.
  • Данные в безопасном хранилище хранятся в закрытом виде и тем самым исключаются случаи непредумышленной «засветки» паролей.
  • Безопасное хранилище исключено из планов обмена, что предотвращает утечку паролей из информационной базы при обмене данными.
работа с безопасным хранилищем в 1с

Другие статьи по теме 1С

Выгрузить табличную часть в Excel

Задача: выгрузить табличную часть формы в файл формата XLSX. К сожалению на прямую это не сделать, но зато мы можем воспользоваться функционалом компонента ПостроительОтчета, который в свою очередь понимает на входе таблицу значений. В итоге нам остаётся лишь выгрузить табличную часть в таблицу значений, которую в свою оочередь скормить построителю отчетов. На выходе будет ТабличныйДокумент, который уже штатно может сохраняться в т.ч. и в формат xlsx. Код получается примерно такой::

&НаСервере
Функция ЭкспортВExcelНаСервере()
	ТабДок = Новый ТабличныйДокумент;
	
		Тз = Новый ТаблицаЗначений;
		тз.Колонки.Добавить("Отделение");
		тз.Колонки.Добавить("Подразделение");
		тз.Колонки.Добавить("ЛС");
		тз.Колонки.Добавить("КодСопоставления");
		тз.Колонки.Добавить("ДатаРождения");
		тз.Колонки.Добавить("МестоРождения");
		тз.Колонки.Добавить("СерияПаспорта");
		тз.Колонки.Добавить("НомерПаспорта");
		тз.Колонки.Добавить("СерияНомерПаспорта");
		тз.Колонки.Добавить("РезультатПроверки");
		
		для каждого стр из объект.РезультатСопоставления цикл
			нс=тз.Добавить();		
			нс.Отделение=стр.Отделение;
			нс.Подразделение=стр.Подразделение;
			нс.ЛС=стр.ЛС;
			нс.КодСопоставления=стр.КодСопоставления;
			нс.ДатаРождения=стр.ДатаРождения;
			нс.МестоРождения=стр.МестоРождения;
			нс.СерияПаспорта=стр.СерияПаспортаС;
			нс.НомерПаспорта=стр.НомерПаспортаС;
			нс.СерияНомерПаспорта=стр.СерияНомерПаспорта;
			нс.РезультатПроверки=стр.РезультатПроверки;
		конеццикла;
		
		Построитель = Новый ПостроительОтчета;
		Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(Тз);
		Построитель.Выполнить();
		Построитель.Вывести(ТабДок);
		
	ИмяВременногоФайлаХар = ПолучитьИмяВременногоФайла(".xlsx");		
	ТабДок.Записать(ИмяВременногоФайлаХар,ТипФайлаТабличногоДокумента.XLSX);
	сообщить(ИмяВременногоФайлаХар);
	
	Двоичное=Новый ДвоичныеДанные(ИмяВременногоФайлаХар);
	Адрес=ПоместитьВоВременноеХранилище(Двоичное,ЭтаФорма.УникальныйИдентификатор);	
	
	Возврат Адрес;
	
КонецФункции

&НаКлиенте
Процедура ЭкспортВExcel(Команда)
	Адрес=ЭкспортВExcelНаСервере();
	
	Описание=Новый ОписаниеПередаваемогоФайла(ПолучитьИмяВременногоФайла(".xlsx"),Адрес);
	МассивОписаний=Новый Массив;
	МассивОписаний.Добавить(Описание);
	ПолучитьФайлы(МассивОписаний,,,Ложь);	
	
	 Для Каждого фф Из МассивОписаний Цикл
	  ЗапуститьПриложение(фф.Имя);
	 КонецЦикла;	
	
КонецПроцедуры

Пользователь нажимает кнопку «Экспорт в эксель», на сервере формируется файл и передаётся на клиент. На клиенте он открывается приложением по умолчанию для данного формата файла. Код получился кросс платформенный, что в наше время очень актуально.

No module named ‘apt_pkg’

Всё началось неплохо (с)… А именно захотел я обновить apache на одном из серверов, Ubuntu на «наисвежайший». Сначала попытался собрать из исходных кодов, но как-то не срослось, а потому чуть погуглив, нашел что в репозитарии ondrej/apache2 всегда лежат уже собраные пакеты самой свежей версии. Казалось бы дело простое:

sudo add-apt-repository ppa:ondrej/apache2
sudo apt update
sudo apt upgrade apache2

Но не тут то было..Получил ошибку «No module named ‘apt_pkg'»:

Traceback (most recent call last):
  File "/usr/bin/add-apt-repository", line 5, in <module>
    import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'

При попытке доустановить пакет через pip3… вышло сообщение, что пакета то такого и нет..

pip install apt_pkg
ERROR: Could not find a version that satisfies the requirement apt_pkg (from versions: none)
ERROR: No matching distribution found for apt_pkg

Долго гуглил почему так, выяснить так и не смог. Единственное что удалось выяснить, что если запускать pip3 для python3.10, то пакет ищется и устанавливается. Возможно дело в как-то криво установленном python3.11 В результате, пришлось перейти обратно на python3.10

update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.10 1
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 2
update-alternatives --list python3

После чего всё штатно обновилось и установилось.

No module named 'apt_pkg'