• Как с помощью Scrapy расфасовать характеристики по колонкам в CSV?

    @aspayr Автор вопроса
    Так и нужен скрипт который будет проверять на консистентность.

    У меня есть похожий скрипт, но он на C#
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Data;
    using DynamicPluginData;
    using System.Text.RegularExpressions;
    using System.Reflection;
    using System.Collections.Specialized;
    using System.IO;
    using LowLevel;
    using System.Net;
    using System.Threading;
    using System.Collections;
    using HtmlAgilityPack;
    
    namespace DatacolDynamicPluginNS
    {
        public class DynamicPluginClass
        {
    
            public static DataTable preExportData(DataTable dataTable, ItemInfo itemInfo, GlobalInfo globalInfo)
            {
               
                //Название поля данных, в которое собрана таблица характеристик 
                string FieldName = "Характеристики";
    
                //Список Xpath выражений для сохранения области, в которой находится название и значение одной характеристики
                List<string> ParameterAreaXpathList = new List<string> {"//li"};
    
                //Список Xpath выражений для сохранения названия характеристики из вырезанной области
                List<string> ParameterNameXpathList = new List<string> {"//div[1]"};
    
                //Список Xpath выражений для сохранения значения характеристики из вырезанной области
                List<string> ParameterValueXpathList = new List<string> {"//div[2]"};
    
                //Список регулярных выражений для сохранения области, в которой находится название и значение одной характеристики
                List<string> ParameterAreaRegexList = new List<string> ();//{"<dl[^<>]*?product-spec[^<>]*?>.*?</dl>"} 
    
                //Список регулярных выражений для сохранения названия характеристики из вырезанной области
                List<string> ParameterNameRegexList = new List<string> ();//{"<span[^<>]*?product-spec__name-inner[^<>]*?>(.*?)<.*?>"}
    
                //Список регулярных выражений для сохранения значения характеристики из вырезанной области
                List<string> ParameterValueRegexList = new List<string> ();//{"<span[^<>]*?product-spec__value-inner[^<>]*?>(.*?)<.*?>"}
    
                bool AreasFound = false;
                bool TitlesFound = false;
                DataTable tempDT = new DataTable();
    
                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    List<string> Areas = getMatches(dataTable.Rows[i][FieldName].ToString(), ParameterAreaXpathList, ParameterAreaRegexList);
    
                    if (Areas.Count == 0) continue;
    
                    AreasFound = true;
    
                    foreach (string Area in Areas)
                    {
                        string Title = getMatch(Area, ParameterNameXpathList, ParameterNameRegexList, 1, true);
    
                        if (Title == "") continue;
    
                        TitlesFound = true;
    
                        if (!dataTable.Columns.Contains(Title))
                        {
                            dataTable.Columns.Add(Title);
                        }
                    }
                }
    
    
                if (!AreasFound) throw new Exception("Области с характеристиками не найдены");
                if (!TitlesFound) throw new Exception("Названия характеристик не найдены");
    
                DataTable tempDT2 = new DataTable();
    
                bool ValuesFound = false;
    
                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    #region Get characteristics
    
                    List<string> Areas = getMatches(dataTable.Rows[i][FieldName].ToString(), ParameterAreaXpathList, ParameterAreaRegexList);
    
                    if (Areas.Count == 0) continue;
    
                    foreach (string Area in Areas)
                    {
                        string Title = getMatch(Area, ParameterNameXpathList, ParameterNameRegexList, 1, true);
    
                        if (Title == "") continue;
    
                        string Value = getMatch(Area, ParameterValueXpathList, ParameterValueRegexList, 1, true);
    
                        if (String.IsNullOrEmpty(Value)) continue;
    
                        ValuesFound = true;
    
                        dataTable.Rows[i][Title] = Value;
                    }
    
                    #endregion
    
                }
    
                if (!ValuesFound) throw new Exception("Значения характеристик не найдены");
                return dataTable;
            }
    
    
            /// <summary>
            /// Получаем список участков
            /// </summary>
            /// <param name="DataTable"></param>
            /// <param name="ParameterAreaXpathList"></param>
            /// <param name="ParameterAreaRegexList"></param>
            public static List<string> getMatches(string RawParameterSource, List<string> ParameterAreaXpathList, List<string> ParameterAreaRegexList, int RegexGroup = 0, bool StripTags = false)
            {
                List<string> RetVal = new List<string>();
    
                HtmlDocument doc = new HtmlDocument();
                doc.LoadHtml(RawParameterSource);
                HtmlDocument docin = new HtmlDocument();
    
                //Поиск по xpath
                foreach (string xpath in ParameterAreaXpathList)
                {
                    if (doc.DocumentNode.SelectNodes(xpath) == null) continue;
    
                    foreach (HtmlNode node in doc.DocumentNode.SelectNodes(xpath))
                    {
                        RetVal.Add(node.OuterHtml);
                    }
    
                }
    
                //Поиск по regex
                foreach (string regex in ParameterAreaRegexList)
                {
                    MatchCollection matches = Regex.Matches(RawParameterSource, regex, RegexOptions.Singleline | RegexOptions.IgnoreCase);
    
                    foreach (Match match in matches)
                    {
                        RetVal.Add(match.Groups[RegexGroup].ToString());
                    }
                }
    
                if (StripTags)
                {
                    for (int i = 0; i < RetVal.Count; i++)
                    {
                        RetVal[i] = extra.strip_tags(RetVal[i]).Trim();
                    }
                }
                return RetVal;
            }
    
            public static string getMatch(string RawParameterSource, List<string> ParameterAreaXpathList, List<string> ParameterAreaRegexList, int RegexGroup = 0, bool StripTags = false)
            {
                List<string> RetValList = getMatches(RawParameterSource, ParameterAreaXpathList, ParameterAreaRegexList,
                    RegexGroup,
                    StripTags);
    
                if (RetValList.Count == 0) return "";
    
                return RetValList[0];
            }
        }
    }


    Но не я его писал и не смогу повторить на Питоне ) Думал что есть уже какое то готовое решение на Scrapy.
    Ответ написан
    Комментировать