Меню
Это черновик для будущей заметки в блог "Парсинг сайтов в элементы инфоблока".
Покажу на простом примере, в заметке будет расширенный вариант с парсингом товаров каталога.

У нас есть некая страница, с такой HTML структурой:
Код
<div class="it">
    <h4 class="ti">Сайдинг-Россия</h4>
    <div class="con">
        Официальный дистрибьютор<br>
        140300, Московская область, г. Егорьевск, ул. Рязанская, д.107с1<br>
        телефон:  +7 (966) 000-36-36<br>
        график работы: ежедневно 9:00—18:00<br>
        email: siding-russia@mail.ru<br>
        https://siding-russia.ru/
    </div>
</div>

<div class="it">
     <h4 class="ti">Виниловая торговая компания</h4>
    <div class="con">
        Официальный дистрибьютор<br>
        141212, Московская область, Пушкинский городской округ, село
        Тарасовка, ул. Центральная, вл.52, стр. 2<br>
        телефон: +7 (495) 799-45-67<br>
        график работы: пн — вс 09:00 — 18:00<br>
        email: sale2@vtcopt.ru<br>
        https://vtcopt.ru/
    </div>
</div>

И так далее любое количество таких блоков

Нам нужно спарсить к себе на сайт при этом каждая строка должна заполниться в свойства инфоблока с соответствующим содержимым.
Для этого нам нужны коды или ID заведомо созданных свойств инфоблока.

Используем следующий скрипт для парсинга:
Код
<?php
// Подключение ядра битрикса
require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");

// Указываем URL страницы, которую нужно скачать и распарсить
$url = 'http/пример-сайта.ru/1.php'; // Замените на нужный сайт и путь

// Загружаем HTML страницы через cURL (можно и через file_get_contents, если настройки позволяют)
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Если нужно, можно добавить настройки авторизации, прокси, юзер-агент и т.п.
$html = curl_exec($ch);
curl_close($ch);

// Проверка успешной загрузки
if (!$html) {
    die("Ошибка загрузки страницы");
}

// Создаем DOMDocument и загружаем HTML
$dom = new DOMDocument();
libxml_use_internal_errors(true); // Отключаем ошибки парсера из-за некорректного HTML
$dom->loadHTML($html);
libxml_clear_errors();

// Используем XPath для поиска нужных элементов
$xpath = new DOMXPath($dom);

// Ищем все блоки с классом 'it'
$blocks = $xpath->query("//*[contains(@class, 'it')]");

$result = []; // Массив для хранения данных

foreach ($blocks as $block) {
    // В каждом блоке ищем заголовок h4 с классом 'ti'
    $titleNode = $xpath->query(".//h4[@class='ti']", $block)->item(0);
    $title = $titleNode ? trim($titleNode->nodeValue) : '';

    // Внутри блока ищем div с классом 'con'
    $conNode = $xpath->query(".//div[@class='con']", $block)->item(0);
    if ($conNode) {
        // Получаем HTML содержимого div, чтобы разбивать по <br>
        $conHTML = $dom->saveHTML($conNode);
        // Разбиваем по тегам <br> (учитываем оба варианта: <br> и <br/>)
        $lines = preg_split('/<br\s*\/?>/i', $conHTML);

        // Очистка каждой линии от тегов и пробелов
        $linesClean = array_map(function($line) {
            return trim(strip_tags($line));
        }, $lines);

        // Добавляем данные в массив
        $result[] = [
            'TITLE' => $title,
            'CONTENT_LINES' => $linesClean,
        ];
    }
}

// Обработка результатов: добавляем в инфоблок
// Подключаем модуль инфоблоков
CModule::IncludeModule("iblock");

// Создаем объект для добавления элементов
$el = new CIBlockElement;

// Идентификатор инфоблока, куда добавляем
$IBLOCK_ID = 4; // Замените на ваш ID инфоблока

foreach ($result as $item) {
    // Тут можно просматривать данные перед добавлением
    //echo '<pre>'; 
    //print_r($item); 
    //echo '</pre>';

    // Формируем свойства для элемента
    $PROP = array();

    // Предполагая, что у вас есть определенные свойства по номерам:
    // Пример адаптируйте под свои свойства:
    if (isset($item['CONTENT_LINES'][0]))
        $PROP[25] = trim($item['CONTENT_LINES'][0]); // например, адрес
    if (isset($item['CONTENT_LINES'][1]))
        $PROP[29] = trim($item['CONTENT_LINES'][1]); // телефон
    if (isset($item['CONTENT_LINES'][2]))
        $PROP[26] = trim($item['CONTENT_LINES'][2]); // И так далее
    if (isset($item['CONTENT_LINES'][3]))
        $PROP[28] = trim($item['CONTENT_LINES'][3]);
    if (isset($item['CONTENT_LINES'][4]))
        $PROP[27] = trim($item['CONTENT_LINES'][4]);
    if (isset($item['CONTENT_LINES'][5]))
        $PROP[30] = trim($item['CONTENT_LINES'][5]);
    if (isset($item['CONTENT_LINES'][6]))
        $PROP[37] = trim($item['CONTENT_LINES'][6]);

    // Создаем массив данных для нового элемента
    $fields = [
        'IBLOCK_ID' => $IBLOCK_ID,
        'NAME' => $item['TITLE'], // название элемента
        'PROPERTY_VALUES' => $PROP,
        'ACTIVE' => 'Y',
        // Можно добавить 'PREVIEW_TEXT' или 'DETAIL_TEXT', если нужно
        //'PREVIEW_TEXT' => implode("\n", $item['CONTENT_LINES']),
    ];

    // Добавляем элемент инфоблока
    $elementId = $el->Add($fields);
    if (!$elementId) {
        echo 'Ошибка добавления элемента: ', $el->LAST_ERROR, "<br>";
    } else {
        echo "Добавлен элемент ID: ", $elementId, "<br>";
    }
}

// Подключаем завершающую часть битрикса
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_after.php');
?>
Да, парсить сайты с помощью PHP может не очень здравая идея. В заметке рассмотрю вариант с парсингом в json с помощью GoLang.
Далее импорт json в инфоблок 1С-Битрикс

Загружаем страницу с другого сайта по URL
Парсим HTML, ищет блоки с классом it
Извлекает заголовки и содержимое
Формирует JSON формат, подходящий для импорта в битрикс (например, массив объектов с нужными полями)
Код
// main.go
package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
    "strings"

    "golang.org/x/net/html"
)

// Структура для вывода данных
type Item struct {
    Title    string   `json:"title"`
    Content  []string `json:"content_lines"`
}

func main() {
    url := "https://пример-сайта.ru/1.php" // замените на ваш URL

    // Загружаем страницу
    resp, err := http.Get(url)
    if err != nil {
        fmt.Printf("Ошибка загрузки страницы: %v\n", err)
        return
    }
    defer resp.Body.Close()

    bodyBytes, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("Ошибка чтения тела ответа: %v\n", err)
        return
    }

    htmlContent := string(bodyBytes)

    // Парсим HTML
    doc, err := html.Parse(strings.NewReader(htmlContent))
    if err != nil {
        fmt.Printf("Ошибка парсинга HTML: %v\n", err)
        return
    }

    // Ищем все блоки с классом 'it'
    var items []Item
    var f func(*html.Node)
    f = func(n *html.Node) {
        if n.Type == html.ElementNode {
            // Проверяем класс
            if hasClass(n, "it") {
                // Внутри ищем h4 class='ti'
                title := ""
                contentLines := []string{}

                // Обходим дочерние узлы для получения данных
                for c := n.FirstChild; c != nil; c = c.NextSibling {
                    if c.Type == html.ElementNode && c.Data == "h4" && hasClass(c, "ti") {
                        title = getTextContent(c)
                    }
                    if c.Type == html.ElementNode && c.Data == "div" && hasClass(c, "con") {
                        // Получаем HTML содержимого div.con
                        lines := getDivContentLines(c)
                        contentLines = lines
                    }
                }

                if title != "" || len(contentLines) > 0 {
                    items = append(items, Item{
                        Title:   title,
                        Content: contentLines,
                    })
                }
            }
        }
        // Рекурсия
        for c := n.FirstChild; c != nil; c = c.NextSibling {
            f(c)
        }
    }

    f(doc)

    // Формируем JSON
    jsonData, err := json.MarshalIndent(items, "", "  ")
    if err != nil {
        fmt.Printf("Ошибка сериализации JSON: %v\n", err)
        return
    }

    // Выводим JSON — его можно сохранить или использовать дальше
    fmt.Println(string(jsonData))
}

// Проверка наличия класса у узла
func hasClass(n *html.Node, class string) bool {
    for _, attr := range n.Attr {
        if attr.Key == "class" {
            classes := strings.Fields(attr.Val)
            for _, c := range classes {
                if c == class {
                    return true
                }
            }
        }
    }
    return false
}

// Получение текстового содержимого узла
func getTextContent(n *html.Node) string {
    var buf strings.Builder
    var f func(*html.Node)
    f = func(node *html.Node) {
        if node.Type == html.TextNode {
            buf.WriteString(node.Data)
        }
        for c := node.FirstChild; c != nil; c = c.NextSibling {
            f(c)
        }
    }
    f(n)
    return strings.TrimSpace(buf.String())
}

// Получение содержимого div с разбиением по <br>
func getDivContentLines(n *html.Node) []string {
    var lines []string
    for c := n.FirstChild; c != nil; c = c.NextSibling {
        if c.Type == html.TextNode {
            // Обработка текста
            text := strings.TrimSpace(c.Data)
            if text != "" {
                lines = append(lines, text)
            }
        } else if c.Type == html.ElementNode && c.Data == "br" {
            // Разделитель для новой строки
            lines = append(lines, "\n")
        } else if c.Type == html.ElementNode {
            // Для других тегов - берем текст
            text := getTextContent(c)
            if text != "" {
                lines = append(lines, text)
            }
        }
    }
    // Можно объединить весь массив и разбить по \n, если нужно
    // Например, объединение
    combined := strings.Join(lines, "\n")
    // Разбиваем по \n
    splitLines := strings.Split(combined, "\n")
    // убираем пустые строки
    var cleaned []string
    for _, line := range splitLines {
        line = strings.TrimSpace(line)
        if line != "" {
            cleaned = append(cleaned, line)
        }
    }
    return cleaned
}
Форма ответов
 
Текст сообщения*
Перетащите файлы
Ничего не найдено
Файл
 

Блог-note: заметки разработчика

Как добавить режим редактирования элементов в собственном компоненте Битрикс

Задача: добавить режим редактирования и удаления элементов в собственном компоненте.

Правильное подключение стилей и скриптов в Битрикс

Есть несколько способов подключения файлов стилей и скриптов, при верстке шаблонов в системе управления 1С-Битрикс. Если...

Вывести свойство привязка к Яндекс Картам в Битрикс

Часто бывает нужно вывести свойство привязка к Яндекс карте в детальном описании элемента. Например в детальной новости ...

Уникальная СЕО информация для каждого торгового предложения в каталоге 1С-Битрикс

Задача: реализовать уникальную мета-информацию для каждого SKU в каталоге. У каждого ТП должны быть свои: заголовок h1, ...

Пошагово получить информацию о заказах и сохранить как Excel (xls)

Задача: Нужно получить информацию о заказах с возможностью указания даты создания "от"" и "до" ...

Добавление своих полей в почтовые шаблоны Битрикс

Иногда нужно внести свои поля в почтовые шаблоны битрикс. Например: добавить имя и номер телефона заказчика в почтовый ш...

Если предложение SKU в корзине, поменять кнопку добавления на "В корзине"

Данная заметка является дополнением к ранее опубликованной: Если товар в корзине, поменять значение input на "В корзине"...

Не дать купить товара больше, чем находится на определенных складах

Задача: в магазине 20 складов, на всех есть остатки но нужно ограничить покупку товара только остатками на двух складах,...

Адаптивное гамбургер меню для битрикс

Заметка коротенькая, но решил оставить ее - так как самому часто нужно нечто подобное. В архиве готовый шаблон для Битри...