MassArticleParser - массовый парсинг статей. Один парсер для всех сайтов.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#51

В примере выше переменная $output перезаписывается результатом функции GetAllImages , в которую на вход подали весь html-код страницы, а не просто код статьи. Поэтому берутся все картинки со страницы, в том числе и счётчики. Режим в данном случае значения не имеет, т.к. картинки берутся не из $output, а из $page_data. Если на вход функции подавать $output, то картинки будут браться только из статьи, если парсер сможет её выделить из кода всей страницы.

А вот как сохранять теги в своём виде:

function GetAllImages(s){
r='';
tmpl='<img src="[SRC]" alt="[ALT]" title="[TITLE]">';
i=stripos(s,'<img');
while(i>0){
i2=strpos(s,'>',i);
if(i2==0){break;}
t=substr(s,i,(i2+1)-i);

src=GetAttribute(t,'src'); a=str_replace('[SRC]',src,tmpl);
alt=GetAttribute(t,'alt'); a=str_replace('[ALT]',alt,a);
title=GetAttribute(t,'title'); a=str_replace('[TITLE]',title,a);
r=r+a+"\r\n";

i=stripos(s,'<img',i+1);
}
return(r);
}

function GetAttribute(tag,attr){
r='';
a=attr+'='; l=strlen(a);
i=stripos(tag,a);
if(i>0){
s=substr(tag,i+l,1);
if(s!='"' && s!="'"){s=' ';n=i+l;}else{n=i+l+1;}
i2=strpos(tag,s,n);
if(i2>0){r=substr(tag,n,i2-n); }
}
return(r);
}

Сиреневым я выделил шаблон по которому сохраняются картинки. Можно, например, просто через точку с запятой сохранять:

tmpl='[SRC];[ALT];[TITLE]';

Функция GetAttribute достаёт из тега значение указанного атрибута.

Чтобы сохранялись только те, у которых есть alt или title, надо строку r=r+a+"\r\n"; заменить на:

if(alt!='' || title!=''){r=r+a+"\r\n";}

К этой же строке можно добавить, например, фильтрацию счётчика liveInternet:

if(strpos(t,'yadro.ru')==0){
if(alt!='' || title!=''){r=r+a+"\r\n";}
}

В таком случае теги, в которых есть yadro.ru , не будут сохраняться.

P.S.

1. Если вы тестируете скрипты на вкладке Scripting в JakoDorgen-е, то учтите, что функция stripos (возвращает позицию первого вхождения подстроки без учета регистра) там отсутствует (забыл добавить).

2. Настройка *savetofolders=0 (сохранять вне папок) игнорируется, если стоит *keyfilenames=1 (имена файлов из кеев). Это делается для того, чтобы статьи с разных сайтов, но с одинаковым названием не перезаписывали друг друга.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#52

Один человек предлагал, чтобы я встроил в парсер перевод текстов на нужный язык. Я отказался потому, что считаю это неуместным функционалом для парсера. Но перевод статей всё же можно сделать через скрипт. Вот пример функции перевода через API Яндекс.Переводчика:

В конец thread_events.txt добавить:

function Translate(text,langs,ukey){
r='';
p='text='+escapedata(text);
url="/api/v1.5/tr.json/translate?lang="+langs+"&key="+ukey+"&format=html";
h="POST "+url+" HTTP/1.1\r\nHost: translate.yandex.net\r\n";
h=h+"Content-Type: application/x-www-form-urlencoded\r\n";
h=h+"Content-Length: "+strlen(p)+"\r\n\r\n";
h=h+p;

nt=0;
do{
r=WebRequest('https://translate.yandex.net'+url,h,'','utf-8');
nt=nt+1;
}while(strpos(r,'HTTP/1.1 200 OK')==0 && nt<2);

if(strpos(r,'"code":200')>0){
i=strpos(r,'"text":["'); if(i>0){ i2=strpos(r,'"]',i);
r=substr(r,i+9,i2-(i+9));
r=str_replace('\n',"\n",r);
r=str_replace('\r',"\r",r);
r=str_replace('\t',"\t",r);
r=str_replace('\"','"',r);
}else{r='';}
}else{r='';}
return(r);
}

function escapedata(text){
r='';
s=15000;
l=strlen(text);
for(i=1;i<=l;i=i+s){
r=r+escapeuri(substr(text,i,s));
}
return(r);
}

А после строки function on_Save(){ вставить:

$output=Translate($output,'ru-en','ваш-api-ключ');

ru-en - направление перевода (с русского на английский).

API-ключ выдается Яндексом бесплатно.

Максимальный размер передаваемого для перевода текста составляет 10 000 символов.

Тексты в тегах (например, в alt) почему-то Яндекс.Переводчиком через API не переводятся, хотя если вручную на https://translate.yandex.ru пробовать, то переводятся.

Ещё обратите внимание, что перевод приходит в экранированном виде. В скрипте есть разэкранирование, но не всех символов:

r=str_replace('\n',"\n",r);
r=str_replace('\r',"\r",r);
r=str_replace('\t',"\t",r);
r=str_replace('\"','"',r);

И, кто не знает, в Яндекс.Переводчике есть лимиты: до 1 000 000 символов в сутки, но не более 10 000 000 символов месяц. Стоимость использования платного API - https://translate.yandex.ru/developers/prices

Какой сервис-переводчик выбрать - решайте сами. Я просто продемонстрировал, как отправлять http-запросы через функцию

WebRequest.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#53

Тестировать скрипты для MassArticleParser-а можно в этой программке - http://jako.tech/jakoscript/

Это интерпретатор скрипта аналогичный вкладке Scripting в JakoDorgen-е.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#54

Как сделать изображения ссылками с урлами, взятыми из файла (случайный урл для каждой ссылки). Создадим файл со списоком урлов:

http://site1.ru/page/
http://site2.ru/page/
http://site3.ru/page/

В файле thread_events.txt:

После function on_Start(){ впишите:

$$linkcount=explode("\r\n",readfile('E:\Parser\linklist.txt','windows-1251'),$$links)-1;
for(i=$$linkcount;i>=0;i=i-1){
if($$links==''){$$linkcount=$$linkcount-1;}
}

E:\Parser\linklist.txt замените на ваш файл с урлами для ссылок.

В конец вставьте эту функцию:

function AddLinks(s){
i=stripos(s,'<img');
while(i>0){
i2=strpos(s,'>',i);
if(i2==0){break;}
t=substr(s,i,(i2+1)-i);
w='<a href="'+$$links[rand(1,$$linkcount)]+'">'+t+'</a>';
s=substr(s,1,i-1)+w+substr(s,i2+1,strlen(s)-i2);
i=stripos(s,'<img',i+strlen(w));
}
return(s);
}

После function on_Save(){ вставьте:

$output=AddLinks($output);

M
На сайте с 04.10.2013
Offline
82
#55

Производительность парсера навысоте, паршу в 35 потоков на процессоре e5 2660 v2

Потребление озу 3 GB, процессора не более 40%, думаю и 50 потоков можно зарядить.

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

Разработчик отзывчивый, оперативно отвечает на почту и помог написать скрипты по моей просьбе, собственно в этом топике он их опубликовал. Продукт стоит своих денег на 100%,

Здесь (https://imonetizeit.ru/site/referral?hash=e9c994975be66785c950cf8c64a2e4d0) дейтинг со смартлинком, все гео
JakoKruzo
На сайте с 04.06.2008
Offline
158
#56

Как спарсить одну и ту же страницу несколько раз, на примере парсинга статей из Яндекс.Рефератов.

Допустим, нужно напарсить рефератов по философии. Указываем в sites.txt ссылку https://yandex.ru/referats/?t=philosophy. Каждый раз, при заходе на эту страницу, отображается новый реферат.

Добавим в конец thread_events.txt эту функцию:

function GetReferat(s){
t='';
i=strpos(s,'<div class="referats__text">');
if(i>0){
i2=strpos(s,'</div><div>',i+28);
t=substr(s,i+28,i2-(i+28));
}
return(t);
}

После function on_Start(){ впишем: $$rnum=0;

А после function on_Save(){ вставим:

r=GetReferat($page_data);
if(r!=''){
$$rnum=$$rnum+1;
writefile($article_dir+'\'+$$rnum+'.txt',r,'windows-1251');
reparsepage();
}else{
stopthread(1);
}

В settings.txt установим:

*pagenestinglimit=0
*parsemainpage=1

Рефераты будут парситься пока вы не остановите парсинг кнопкой "STOP ALL". В статусе будет всё время отображаться "Parsing 1/1". Если вы хотите видеть, какой по счёту реферат парсится, то добавьте после $$rnum=$$rnum+1; эту строку: statusbox_show("Парсинг : "+$$rnum);

Если нужно делать паузу между загрузками страницы, то добавьте после reparsepage(); вызов паузы: sleep(2); . В скобках указывается кол-во секунд (в данном примере делается пауза 2 секунды).

Для повторения парсинга страницы используется команда reparsepage(); , которая указывает, что дальше будет парситься не следующая страница, а эта же.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#57

Сделал обновление 2.0.9.

Добавил в скриптинг переменные, которые начинаются с $$$. Такие переменные видны везде и всегда. Если задать такую переменную

в events.txt, то она будет видна и в thread_events.txt, и будет существовать до момента закрытия программы.

Напомню ещё раз о переменных:

1. Обычные локальные. Не начинаются со знака $. Например: myvar=100; . Такая переменная видна только внутри своей функции (метода).

2. Переменные, которые видны во всех функциях скрипта. Начинаются с $. Например: $myvar=100; . Такие переменные удаляются после завершения работы скрипта.

3. Переменные, которые видны во всех функциях, но не удаляются после завершения работы скрипта. Начинаются с $$. Удаляются по завершению работы потока парсинга.

4. Переменные, которые начинаются с $$$. В отличие от всех предыдущих, которые существовали только в пределах своего потока парсинга, такие переменные являются общими для всех потоков, видны во всех скриптах, не удаляются по завершении работы потока и всего парсинга.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#58

Обновление 2.1.0.

1. Исправлена ошибка с парсингом отдельных урлов.

Для парсинга отдельных урлов указывайте: *pagenestinglimit=0, *parsemainpage=1, *savetofolders=0.

2. Появилась возможность задать минимальную длину статьи: *minarticlelen=500. В данном примере будут сохраняться только статьи длиной более 500 символов. Теги, пробелы, переносы и табуляции считаются!

Если нужно учитывать только длину самого текста без пробелов, тегов и прочего, то нужно добавить английскую си: *minarticlelen=1000c.

3. Настройка Link limit, ограничивающая кол-во обходимых ссылок, перенесена с формы в файл настроек: *linklimit=9999999.

4. Добавлена возможность переключения между разными файлами настроек. Файлы настроек должны находиться в папке с программой и начинаться с settings. Например: settings-test.txt, settings2.txt.

5. Добавлена возможность указать признаки страниц, которые не нужно парсить. Для этого служит настройка: *badpagessigns= . Например, если в результаты парсинга попадают страницы категорий, на которых есть строки "Архив рубрики:" и "Архив метки:", то для их исключения надо указать: *badpagessigns=Архив рубрики:,Архив метки: . Если на странице встретится одна из этих строк, то эта страница парситься не будет.

Кстати, теперь запятые в строках, которые не являются разделителями, можно экранировать обратным слешем.

6. Можно указывать строки, которые должны обязательно присутствовать на странице в настройке *goodpagessigns=<body . В этом примере указан текст <body. Это значит, что страницы, в коде которых нет <body , не будут парситься. Будут парситься только страницы, содержащие хотя бы одну из указанных строк. Это сделано для того, чтобы исключить из результатов парсинга не html страницы, например электронные книги, архивы, офисные файлы.

7. В скрипт добавлена переменная $http_headers, содержащая http-заголовки страницы.

Также, добавлена переменная $output_file (только для записи), в которой можно задать имя файла, в который сохранится статья.

Для reparsepage();, которая указывает, что нужно перепарсить страницу, добавлена возможность сохранения статьи: reparsepage(1);. Так статья будет сохраняться, несмотря на то, что страница будет перепарсена. Если же 1 не вписывать, то содержимое переменной $output будет очищаться, т.е. статья не будет сохраняться. Вот переделанный пример парсинга Яндекс.Рефератов:

$output=GetReferat($page_data);
if($output!=''){
$$rnum=$$rnum+1;
$output_file=$$rnum+'.txt';
reparsepage(1);
}else{
stopthread(1);
}

8. Исправил в скрипте баг с return(); . Теперь выход из функции выполняется.

---------- Добавлено 24.09.2018 в 13:39 ----------

Замените старый MassArticleParser.exe новым и скопируйте last_settings.txt (в нём сохраняются последние использованные настройки).

Добавьте в settings.txt:

*minarticlelen=70
*badpagessigns=
*goodpagessigns=<body
*linklimit=9999999

---------- Добавлено 24.09.2018 в 13:43 ----------

Запуск с командной строки теперь: Profile(файл настроек без расширения);Threads(кол-во потоков);Do not update thread list(не обновлять список потоков)

Пример: settings;5;0

JakoKruzo
На сайте с 04.06.2008
Offline
158
#59

Обновление 2.1.1.

1. Исправил баг с загрузкой списка сайтов и настроек, если используется перевод строки \n, а не \r\n.

2. Сделал возможным указывать одновременно *keyfilenames=1 (имена файлов из названия статей) и *savetofolders=0 (сохранять не в отдельные папки, а в общую). К именам файлов статей с одинаковым названием будут добавляться (2), (3) и т.д....

3. Аналогично выбору файла настроек, добавил возможность выбора шаблона. Файлы шаблонов должны начинаться с template. Также добавил возможность установить максимальное время парсинга сайта (Auto abort after), при превышении которого будет делаться сброс потока.

4. Файлы настроек, шаблоны, thread_events.txt, events.txt и sites.txt должны быть в кодировке utf-8.

Запуск с командной строки теперь: Profile;Template;Threads;Do not update thread list. Пример: settings2;template-test;5;0.

Замените старый MassArticleParser.exe новым.

JakoKruzo
На сайте с 04.06.2008
Offline
158
#60

Обновление 2.1.2.

1. Улучшил определение страниц, которые закрыты от индексации в robots.txt, и которые не нужно парсить. Все, кто включили настройку checkrobotsfile обязательно обновите программу! В предыдущих версиях ссылки с закрытых страниц не парсились, из-за чего сайты обходились не полностью, особенно в тех случаях, когда вебмастера закрывают от индексации страницы категорий.

В настройках теперь можно указать, директивы каких юзер-агентов надо учитывать: *checkrobotsfile=1{*,Yandex,GoogleBot} . Если указать просто *checkrobotsfile=1, то будут учитываться все disallow и allow всех юзер-агентов. Я рекомендую указывать с юзер-агентами.

2. Добавил настройку *parsecategorypages=1, которая включает парсинг страниц категорий. По умолчанию с них парсятся только ссылки. В скрипт введена переменная $page_iscategory, значение которой указывает, является ли текущая страница категорией (1 - да, 0 - нет).

Пример, как найти все страницы сайта, http код которых отличен от 200:

В настройках ставим:

*parsecategorypages=1
*goodpagessigns=
*badpagessigns=
*scripting=1
*allowemptyarticles=1
*parsemainpage=1
*keyfilenames=0

В thread_events.txt после function on_Save(){ впишите:

if(strpos($http_headers,'200 OK')==0){$output=$page_url+"\r\n\r\n"+$http_headers+$page_data;}else{$output='';}

Без настройки *parsecategorypages=1 этот скрипт не обрабатывал бы страницы категорий.

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий