» Быстрый парсер html кода на Delphi Borland Delphi. Базы данных. Создание сайтов. Блог программистов


Блог программистов




20089 Авг

Быстрый парсер html кода на Delphi

Что такое парсер? Парсер – это программа, которая парсит текст, по заданному алгоритму.

Что такое парсить? Парсить – анализировать и расставлять символы, входящие в текст в соответствии заложенного алгоритма, например, для удобного восприятия текста программистом.

Для чего нужен парсер? Парсер я использую для приведения html тегов к единой структуре: одинаковый размер букв, новый тег на новой строчке, удаление пустых строк.

Кроме структурирования информации с помощью парсера, можно добавить алгоритмы логического изменения текстов. Исправления орфографических ошибок, перевода на другой язык, в том числе и на машинные коды, скрипты.

Распарсить можно любую информацию по любому алгоритму, результатом проделанной работы будет та же информация, представленная в ином виде.

Далее привожу код структурирования тегов, цель работы алгоритма – разместить по 1 тегу на каждую строчку memo. В рабочей версии кода программа загружает Html страницы согласно их вложенности в сайте и парсит их, после чего заменяет их.

Для зашиты от дураков оставлю часть кода, который был в основной программе, для демонстрации просто удалите код под комментариями — ///


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button7: TButton;
Button13: TButton;
Memo1: TMemo;
Memo2: TMemo;
procedure Button7Click(Sender: TObject);
procedure Button13Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button7Click(Sender: TObject);
label 1;
var
i,j,k,g:integer;
bol:boolean;
position:integer;
str:string;
begin
//chdir(edit1.Text); /// рабочая папка
//poiskpapki; /// процедура для создания списка файлов в папке.

memo2.Clear;

///здесь был код загрузки следующего файла

for i:= 0 to memo1.Lines.Count - 1 do
begin
str:= memo1.Lines;

1:
position := AnsiPos('>', str);

if position<>0 then
begin

memo2.Lines.Add(copy(str,1,position));
delete(str,1,position);
goto 1;
end;
if position=0 then memo2.Lines.Add(str);

end;
memo1.Text:=memo2.Text;

///здесь был код сохранения следующего файла

//продолжаем парсить
button13.Click;
end;

procedure TForm1.Button13Click(Sender: TObject);
label 1;
var
i,j,k,g:integer;
bol:boolean;
position:integer;
str:string;
begin
//chdir(edit1.Text); /// рабочая папка
//poiskpapki; /// процедура для создания списка файлов в папке.

memo2.Clear;
///здесь был код загрузки следующего файла
for i:= 0 to memo1.Lines.Count - 1 do
begin
str:= memo1.Lines;

1:
position := AnsiPos('<', str); if position>1 then
begin

memo2.Lines.Add(copy(str,1,position-1));
delete(str,1,position-1);
goto 1;
end;
memo2.Lines.Add(str);

///здесь был код сохранения следующего файла.

end;

//продолжаем парсить убираем пустые строки

// здесь был код.
end;

end.

В алгоритме используется рекурсивный цикл перенос до и после знаков открытии закрытии тегов.

Что называют парсерами? Я сделал поиск по форуму по ключевому слову – парсер, движок мне предложил ряд тем, в которых обсуждалось использование и применение парсера. Попробую прокомментировать эти темы, и по возможности дать ответ.

26.04.2007, 16:39 на форуме – programmersforum.ru была создана тема — XML Parser с поддержкой XSLT

Я пишу электронный учебник. Текст хранится в XML файле. При загрузке файла строится дерево по главам в TreeView, а сам текст отображается в RichView. И вот надо чтобы текст отображался со всеми ссылками, картинками, мультимедиа и т.д. В данный момент я добиться этого не могу. У меня отображается простой текст

На тот момент я ничего не смог посоветовать, а сейчас могу сказать, что вопрос был не совсем корректный. Парсером можно только создать структуру, изменить ее, но для отображения нужно создавать инструменты, которые будут по-другому называться.

27.10.2007, 18:29 на форуме – programmersforum.ru была создана тема — Парсер для обработки тагов

Есть некоторый текст из N символов. В этом тексте содержатся разные таги (table, tr, td, img, a). Нужно этот текст разделить на несколько равных частей, т.е сделать постраничный вывод для этого текста. Возникают такие ситуации, когда при разделении текста половина тага находится в одной части, другая половина находится в другой. Чтобы этого избежать, нужно обрабатывать эти таги. Может быть кто-нибудь подскажет, есть ли готовые решения подобных парсеров или же может кто делал что-то подобное. Буду признателен за любую информацию.

Отвечаю, есть решение, с него и начал эту статью, код представлен выше.

07.01.2008, 00:54 на форуме – programmersforum.ru была создана тема — пример парсинга

procedure TForm1.Button1Click(Sender: TObject);
var
Stream: TStream;
s: string;
begin
Stream := TMemoryStream.Create;
try
{ получаем текст области редактирования и помещаем его в поток }
s := memo1.Text;
Stream.WriteBuffer(s[1], length(s));
{ сбрасываем стартовую позицию потока и создаем парсер }
Stream.Position := 0;
with TParser.Create(Stream) do
try
{ "добываем" числа и добавляем их в список }
while Token <> toEOF do
begin
CheckToken(toInteger); { возбуждаем исключение, если не toInteger }
Listbox1.Items.Add(IntToStr(TokenInt));
NextToken;
end;
finally
Free;
end;
finally
Stream.Free;
end;

end;

end.

Пыталься переделать под String не чего не выходит он в listbox выводит по буквено тоесть слово:
Например
Выведет так:
Н
а
п
р
и
м
е
р

Ответ дали там же на форуме –

BOBAH13

procedure TForm1.Button1Click(Sender: TObject);
var
Stream: TStream;
s: string;
begin
Stream := TMemoryStream.Create;
try
{ получаем текст области редактирования и помещаем его в поток }
s := memo1.Text;
Stream.WriteBuffer(s[1], length(s));
{ сбрасываем стартовую позицию потока и создаем парсер }
Stream.Position := 0;
with TParser.Create(Stream) do
try
{ "добываем" числа и добавляем их в список }
s := '';
while Token <> toEOF do
begin
CheckToken(toInteger); { возбуждаем исключение, если не toInteger }
//Listbox1.Items.Add(IntToStr(TokenInt)); -->
s := s + IntToStr(TokenInt);
NextToken;
end;
finally
Free;
end;
finally
Stream.Free;
end;

end;

end.

mihali4

Вован вам ответил на ваш вопрос — как сделать, чтобы символы выводились в строку, а не в столбец (упустил, правда, один оператор — Listbox1.Items.Add(s), но это только от того, что торопился вам помочь побыстрее).


17.01.2008, 18:13, на форуме – programmersforum.ru была создана тема — Как работать с XML?

Мне необходимо прочитать данные из XML файла в массив записей! Я пытался разобраться с XMLDocument но у меня не получилось!! Подскажите, как это сделать!

Вот XML:


<?xml version="1.0"?>
<music>
<muz>
<name>No Artist - No Album</name>
<filename>c:/Muz/NoArtist.mp3</filemane>
<length>247</length>
</muz>
<muz>
<name>No Artist - No Album</name>
<filename>c:/Muz/NoArtist1.mp3</filemane>
<length>203</length>
</muz>
</music>

А вот в этом должно всё быть:


Muz=Record
name:String;
filename:String;
length:Word;
end;

Music=Array of Muz;

Mutabor

Тут все очевидно — нужен парсер, либо самописный либо стандартный. Так как это XML, ясно что есть стандартные, ты не первый кому это надо.
Если вышеуказаная структура это все что требуется, за полчаса можно самому написать, чтоб теги читал. Ключевая функция Pos, ну и еще для копирования одна две понадобятся.

BOBAH13

Из личного опыта пишу:

// моя функция - копирайт :)
function XMLGetChild(Root: IXMLDOMNode; NodeName: String): IXMLDOMNode;
var
Elem: IXMLDOMNode;
begin
Elem := Root.firstChild;
while (Elem <> NIL) do
begin
if (Elem.nodeName = NodeName) then
Break;
Elem := Elem.nextSibling;
end;
Result := Elem;
end;

var
coDoc: CoDOMDocument;
Doc: IXMLDOMDocument;
Root: IXMLDOMElement;
Elem: IXMLDOMNode;
begin
Doc := coDoc.Create;
Doc.Set_async(False);
Doc.loadXML(Ваш xml текст);
Root := Doc.Get_documentElement;
Elem := XMLGetChild(Root, Имя узла тобиш вашего Muz);
// остальные узлы по аналогии разгребаем в цикле
end;

Квэнди

SimDesign NativeXml v2.37 for.Delphi
и подобных компонент есть еще множество ) просто этот наиболее функционален

Рассмотрю пример номер 5 в XML файле хранится информации о картинке, т.е. картинка в XML структуре.

<?xml version="1.0" encoding="UTF-8"?>
<TForm1 Name="Form1">
<Components>
<TImage Name="Image1">
<Left>8</Left>
<Top>24</Top>
<Width>200</Width>
<Height>150</Height>
<Cursor>crCross</Cursor>
<AutoSize>True</AutoSize>
<Center>True</Center>
<Constraints>(TSizeConstraints)
<MaxWidth>600</MaxWidth>
</Constraints>
<Picture>(TPicture)
<DefinedProperties>
BERhdGEK0l8BAAdUQml0bWFwxl8BAEJNxl8BAAAAAAA2AAAAKAAAAMgAAACWAAAAAQAYAAAAAACQ
XwEAEwsAABMLAAAAAAAAAAAAAAcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcIBQcIBAcIBAcIBAUK
BQQKBQMJBAMJBAQKBQQKBQQKBQQKBQQKBQQKBQQKBQQKBQQJCAMVGQMiKAgXGwYLCgUKCQMIBwUK
CQcMCwcMCwUKCQUKCQQKBgQKBQQKBQQKBQMJBAMJBAQKBQQKBQQKBQYMBwQKBQQKBQMJBAMJBAQK
BQQKBQgICAgICAcHBwcHBwcHBwcHBwcHBwYGBggICAcHBwgICAgICAcKBQwJBxAMCgsNCQkUDAQf
DgAxFAJCGwNMJQg2NQIlLQYTFAIOBQgKBQkGBAkICAcHBwcHBwcHBwcHBwQHBwYJCQcKCQYKCQYP
FgYRGgQRHAMRHgcYIAY6MARNNgdOOAZROARaPQJgPgJeOwFiPgJpRAJpRAJiPgFfOgJhPAdqRAVp
<Далее подобные коды…>

</DefinedProperties>
</Picture>
<PopupMenu>PopupMenu1</PopupMenu>
<OnClick>Image1Click</OnClick>
</TImage>
<TLabel Name="Label1">
<Left>8</Left>
<Top>8</Top>
<Width>38</Width>
<Height>13</Height>
<Caption>Image1:</Caption>
</TLabel>
<TLabel Name="Label2">
<Left>224</Left>
<Top>8</Top>
<Width>73</Width>
<Height>13</Height>
<Caption>Object as XML:</Caption>
</TLabel>
<TImage Name="Image2">
<Left>8</Left>
<Top>256</Top>
<Width>200</Width>
<Height>150</Height>
</TImage>
<TLabel Name="Label3">
<Left>8</Left>
<Top>240</Top>
<Width>38</Width>
<Height>13</Height>
<Caption>Image2:</Caption>
</TLabel>
<TMemo Name="mmXml">
<Left>224</Left>
<Top>24</Top>
<Width>361</Width>
<Height>476</Height>
<Anchors>[akLeft,akTop,akRight,akBottom]</Anchors>
<Lines>(TMemoStrings)
<DefinedProperties>
B1N0cmluZ3MBBglIaSB0aGVyZSEGAAYfVGhhbmtzIGZvciB0cnlpbmcgb3V0IHRoZSBkZW1vLgYA
BgpOaWxzIEhhZWNrBhB3d3cuc2ltZGVzaWduLm5sAA==
</DefinedProperties>
</Lines>
<ScrollBars>ssBoth</ScrollBars>
<TabOrder>0</TabOrder>
</TMemo>
<TButton Name="btnSaveImage">
<Left>8</Left>
<Top>183</Top>
<Width>177</Width>
<Height>25</Height>
<Caption>Convert Image Object to XML</Caption>
<TabOrder>1</TabOrder>
<OnClick>btnSaveImageClick</OnClick>
</TButton>
<TButton Name="btnLoadImage">
<Left>8</Left>
<Top>208</Top>
<Width>177</Width>
<Height>25</Height>
<Caption>Load Image2 From XML</Caption>
<TabOrder>2</TabOrder>
<OnClick>btnLoadImageClick</OnClick>
</TButton>
<TStatusBar Name="StatusBar1">
<Left>0</Left>
<Top>503</Top>
<Width>587</Width>
<Height>19</Height>
<Panels>(TStatusPanels)
<TStatusPanel>
<Text>Bli</Text>
<Width>50</Width>
</TStatusPanel>
<TStatusPanel>
<Text>Blu</Text>
<Width>50</Width>
</TStatusPanel>
<TStatusPanel>
<Text>Bla</Text>
<Width>50</Width>
</TStatusPanel>
</Panels>
<SimplePanel>False</SimplePanel>
</TStatusBar>
<TButton Name="btnSaveForm">
<Left>8</Left>
<Top>423</Top>
<Width>177</Width>
<Height>25</Height>
<Caption>Convert whole form to XML</Caption>
<TabOrder>4</TabOrder>
<OnClick>btnSaveFormClick</OnClick>
</TButton>
<TButton Name="btnLoadForm">
<Left>8</Left>
<Top>447</Top>
<Width>177</Width>
<Height>25</Height>
<Caption>Create new form from XML</Caption>
<TabOrder>5</TabOrder>
<OnClick>btnLoadFormClick</OnClick>
</TButton>
<TButton Name="btnClear">
<Left>304</Left>
<Top>6</Top>
<Width>75</Width>
<Height>17</Height>
<Caption>Clear</Caption>
<TabOrder>6</TabOrder>
<OnClick>btnClearClick</OnClick>
</TButton>
<TCheckBox Name="chbRecreate">
<Left>16</Left>
<Top>472</Top>
<Width>153</Width>
<Height>17</Height>
<Caption>Recreate from scratch</Caption>
<TabOrder>7</TabOrder>
</TCheckBox>
<TPopupMenu Name="PopupMenu1">
<Components>
<TMenuItem>
<AutoHotkeys>maAutomatic</AutoHotkeys>
<AutoLineReduction>maAutomatic</AutoLineReduction>
</TMenuItem>
</Components>
<DefinedProperties>
BExlZnQDkAADVG9wAig=
</DefinedProperties>
</TPopupMenu>
<TMenuItem Name="mnuTest">
<Caption>Test</Caption>
<OnClick>mnuTestClick</OnClick>
</TMenuItem>
<TMainMenu Name="MainMenu1">
<Components>
<TMenuItem>
<AutoHotkeys>maAutomatic</AutoHotkeys>
<AutoLineReduction>maAutomatic</AutoLineReduction>
</TMenuItem>
</Components>
<DefinedProperties>
BExlZnQDEAIDVG9wAgg=
</DefinedProperties>
</TMainMenu>
<TMenuItem Name="File1">
<Caption>&amp;File</Caption>
</TMenuItem>
<TMenuItem Name="mnuLoad">
<Caption>&amp;Load and create form from XML</Caption>
<OnClick>mnuLoadClick</OnClick>
</TMenuItem>
<TMenuItem Name="mnuSave">
<Caption>&amp;Save form to XML</Caption>
<OnClick>mnuSaveClick</OnClick>
</TMenuItem>
<TMenuItem Name="mnuExit">
<Caption>&amp;Exit</Caption>
<OnClick>mnuExitClick</OnClick>
</TMenuItem>
</Components>
<Left>358</Left>
<Top>219</Top>
<Width>595</Width>
<Height>568</Height>
<ActiveControl>mmXml</ActiveControl>
<Caption>Objects to XML Test Application</Caption>
<Color>clBtnFace</Color>
<Font>(TFont)
<Charset>DEFAULT_CHARSET</Charset>
<Color>clWindowText</Color>
<Height>-11</Height>
<Name>MS Sans Serif</Name>
<Style>[]</Style>
</Font>
<Menu>MainMenu1</Menu>
<OldCreateOrder>False</OldCreateOrder>
<Visible>True</Visible>
<OnClose>FormClose</OnClose>
<Image>Image1</Image>
<StatusBar>StatusBar1</StatusBar>
<DefinedProperties>
DVBpeGVsc1BlckluY2gCYApUZXh0SGVpZ2h0Ag0=
</DefinedProperties>
</TForm1>

Анонсируя следующий решенный вопрос на форуме, замечу, что использовал стандартные решения для создания сложной структуры с атрибутами. Но пришел к более простой реализации размещения тегов, представленный в начале статьи. Почему? Потому что процесс создания структуры занимал неоправданно много времени, для использования в цикле нужно отслеживать процесс выполнении кода, завершение процесса парсинга. Из-за различного размера страниц и прочих параметров, довольно сложно предсказать какое количество времени нужно на выполнение парсинга, при создании условий цикла.

29.02.2008, 22:48 на форуме – programmersforum.ru была создана тема — Распарсить HTML

Камрады, возникла следующая проблема: есть HTML файл произвольного содержания, его требуется распарсить следующим образом:
1. тип контейнера
2. атрибуты
3. количество вложенных контейнеров
4. данные контейнера (если есть)
5. указатели на вложенные контейнеры
.
Каждый вложенный контейнер должен описываться такой же структурой…
Даже не знаю с какой стороны подступиться… Есть идеи?

Спецификации HTML 1.0 вполне хватит.

Я уже думал по этому поводу регулярных выражений, но как, допустим, отпарсить

B_N

Так же как и всегда: создаем по «типу» (кавычки относятся к условностям таких понятий в PHP) на каждый тэг, образующий объекты, определяем не такую уж сложную функцию parse, берущую аргументом ссылку на текущий объект одного из таких типов и на корневой, или напрямую, или через путем прохода по объектам вверх, создаем корневой объект () и вызываем с ним parse. Встретит она по ходу дела какой-нибудь «объектный» тэг, скажем

, значит создает еще объект, делает в текущем объекте дочерний и вызывает сама себя уже над ним, встретит

(причем, не первый попавшийся, а именно «свой», «первый попавшийся» будут видеть вложеные вызовы), значит завершается.

Johnatan

Рекурсивная функция с регулярными выражениями. Как сказал коллега, то практически это возможно только с XML/XHTML, потому что у них очень строгий синтаксис.

Ну, например, программа начинает парсинг, находит <div id=»menu»>, значит в программе отмечаем, что «menu» открылось, ищем следующий <div, опять открываем следующий… Потом зная сколько блоков было открыто — ищем ровно столько же закрывающих маркеров. Всё что между блочными маркерами «menu» — то и есть меню.. Всё что внутри блочных маркеров — подменю и т.д.

Перед тем как парсить страницу, я бы очень рекомендовал её проверить валидатором, чтобы точно знать, что там нет ошибок, а то парсер с ума сойдёт, если где-то забыли закрыть один блок.

А вообще, этот скрипт, фактически, часть броузера. Нужно поискать исходники броузеров и посмотреть как это делается там.

B_N

Ну почему же. Знаете же как — хорошие мысли приходят оновременно. Кстати, Вы зря пишете, что «парсер с ума сойдёт». Он просто раньше времени и не на должном месте (тэге) вернется к корню — сей конфуз, в том числе, и будет индикатором плохого файла.

Johnatan

Кстати, возможно вот это поможет:
http://validator.w3.org/source/
Ведь валидатор делает фактически то же самое.. Он парсит код.

Топикстартер – Табурет

Повтою алгоритм для себя:
1. за начало объекта берём любой тег (/<[^>]+>/) кроме непарных (


http://validator.w3.org/source/ — Есть другая хорошая штука — tidy — он и валидатор и исправлять корявки умеет.

Далее пример того, что парсить можно любую информацию, создавая необходимые структуры.

25.03.2008, 22:47 на форуме – programmersforum.ru была создана тема — Парсер файловой системы FAT32

Необходимо написать упрощенный парсер файловой системы FAT32,
который будет выводить список файлов и директорий с
поддиректориями заданного диска.
Основные моменты, которые необходимо будет рассмотреть:
1. Необходимо разработать MFC приложение ввиде модального диалога
с необходимыми для отображения и ввода контролами(в простейшем
варианте это окно для ввода имени диска и дерево для отображения
структуры файлов и папок).
2. Найти в интернете описание низкоуровневого формата файловой системы FAT32.
Понять как и что храниться. И там же найти как открыть
логический диск и получить к нему доступ.
3. Последовательно изучать формат, параллельно реализуя в коде его
поддержку для достижения конечной цели — отображения структуры
папок ввиде дерева и навигации по нему.

Интересует FAT32 под XP.

B_N

Просто открываете «файл» «\\.\PHYSICALDRIVE0» (Ну или 1, 2… какой по счёту диск нужен) и работаете с диском, как с файлом.
CreateFile

Комментарии

  1. Апрель 13th, 2009 | 14:05

    Вот этот код меня немного смущает:
    1:
    position := AnsiPos(’1 then
    begin
    memo2.Lines.Add(copy(str,1,position-1));
    delete(str,1,position-1);
    goto 1;
    end;
    Что же именно… Как тут всё происходит? Ищется первое упоминание и, если находится, добавляется и в исходной строке всё удаляется до него. Считаю это удаление лишним, я всегда делаю в цикле (а не goto) и использую PosEx — в этой функции указываем с какого места искать. В результате экономится время, особенно при большом тексте для парсинга
    Сейчас думал найти свой код, да что-то под руку не попадается, если че позже скину для развития темы)

  2. Сентябрь 18th, 2009 | 20:00

    очень полезное. огромное спасибо

  3. dfm
    Сентябрь 28th, 2009 | 10:50

    Ну, что сказать. Хорошая подборка. Многим пригодится.

  4. Ноябрь 12th, 2009 | 12:46

    Спасибо, у меня курсовая и я нуждався в парсенге html файла, ваша стаття мне очень помогла

  5. Январь 20th, 2010 | 12:19

    спасибо. Не знал таких терминов 😕

  6. Апрель 24th, 2010 | 16:04

    Спасибо, поправил у себя!

  7. Май 28th, 2010 | 09:16

    Интересный пример, хотя немного запарено. А как показать структуру html файла в TTreeView — типа Мозиллы?

  8. Июль 31st, 2010 | 16:12

    очень полезное. огромное спасибо

  9. Вася
    Сентябрь 28th, 2010 | 13:31

    Код конечно писец)). Походу чувак в программировании не очень шарит

  10. Alman
    Декабрь 29th, 2010 | 02:10

    Главное не код. Главное — идея! 🙂

  11. Февраль 3rd, 2011 | 22:34

    Мне, как начинающему программеру, эта мнфа очень полезна. Спасибо Вам огромное!

  12. Июнь 30th, 2012 | 01:54

    Лучший парсер — это универсальный парсер

  13. Июнь 30th, 2012 | 01:58

    Сбор внешних ссылок с сайта является важным этапом оценки качества донора для покупки ссылок. Критерии оценки на базе этого параметра у каждого сеошника могут несколько отличаться, но вряд ли кто-нибудь поспорить о его важности.

  14. klientsbasing
    Январь 9th, 2014 | 14:18

    [b]База данных предприятий-компаний России, Украины (2ГИС, 90
    регионов) -2013[/b]
    Тип: БД
    Содержание базы: название предприятия, отрасль деятельности,
    адрес, телефон стационарный, телефон сотовый, email,
    гео-координаты.
    Информация, представленная в базах 2 гис может быть
    использована отделом продаж для подготовки и рассылки
    коммерческих предложений потенциальным клиентам или просто
    для учета своих клиентов.
    Регион: РФ-Украина
    Формат: Microsoft Excel
    Количество записей: Много, регионы подсчитаны.
    Актуализация: ноябрь 2013
    Для проверки вышлю базу по одному городу.
    Для заказа доступно:
    — выгрузку города целиком
    — выгрузку компаний отдельной тематики
    — выгрузку разделов или рубрик по рубрикатору

    ICQ: 658548888

    [b]База email предприятий РФ — 2013[/b]
    Вытянута из баз ДубльГис, количество: 564694
    актуализация: ноябрь 2013 г

    ICQ: 658548888

    [b]База email-адресов mail.ru и yandex.ru[/b]
    Идеально подойдёт
    для почтовой рассылки
    Количество — 160к.

    ICQ — 658548888

    [b]База данных с сайта ruzakaz.com[/b]
    Содержание базы: название предприятия, отрасль деятельности,
    адрес, контактное лицо, телефон, факс, email, тип учреждения,
    уровень, полномочия, бюджет, ИНН, ОГРН, ОКПО, ОКАТО, ОКОГО,
    URL.
    Информация, представленная в базах ruzakaz.com может быть
    использована для подготовки и рассылки коммерческих
    предложений потенциальным клиентам.
    Регион: РФ.
    Формат: Microsoft Excel
    Количество записей: более 200, 000.
    Актуализация: ноябрь 2013
    Для проверки вышлю базу по одной рубрике.
    Для заказа доступно:
    — выгрузка рубрики
    — выгрузка компаний отдельной тематики

    ICQ: 658548888

    [b]База email с сайта b2bpoisk.ru[/b]
    База отлично подойдёт для почтовой рассылки.
    Очищена от дублей и верифицирована. Дата сбора — 12.12.2013 г.

    ICQ: 658548888