• XSS.stack #1 – первый литературный журнал от юзеров форума

Парсинг... Google

DiegO

RAM
Пользователь
Регистрация
28.07.2010
Сообщения
140
Реакции
2
Привет всем мемберам дамаги. Прошё помоч новичку написать парсер для google на php и (или) как пользоваться функцией preg_match_all() а то я по ней не чё не понял. Мне надо что бы по запросу показывались только линки на страницу со всех страницы.
К примеру что бы по запросу Virus (http://www.google.ru/search?client=opera&rls=ru&q=Virus&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest) выдало:

http://ru.wikipedia.org/wiki/Вирусы
http://ru.wikipedia.org/wiki/Компьютерный_вирус
http://www.google.ru/search?q=Virus&hl=ru&...oI&ved=0CEUQqAI
http://www.securitylab.ru/virus/
И т.д.

Я пишу одно чудо и если что получится то выложу сюда!

Я на вас очень надеюсь... помогите пожалуйсто!
 
DiegO, по запросу "php google parser" имеется куча результатов ;)
Могу посоветовать поковырять парсер на Perl, что пользовал я:
Код:
#! /usr/bin/perl

#  ===::: google parser v0.8 :::===
#            (c)oded by drmist\STNC
#            www.security-teams.net

use IO::Socket::INET;

$server = "google.com";
$port = 80;
$count = 0;
$search = "";
@found = ();
@dn = ();

if((@ARGV < 2)||(@ARGV > 8)||(@ARGV % 2 > 0)) { usage(); exit; }

$i = 0;
while($i < @ARGV)
{
 if($ARGV[$i] eq "-s"){ $server = $ARGV[$i+1]; }
 elsif($ARGV[$i] eq "-p"){ $port = $ARGV[$i+1]; }
 elsif($ARGV[$i] eq "-r"){ $search = $ARGV[$i+1]; }
 elsif($ARGV[$i] eq "-n"){ $count = $ARGV[$i+1]; }
 else { print "Invalid key: ".$ARGV[$i]."\n"; exit; }
 $i += 2;
}

if($search eq ""){ usage(); exit; }
$search =~ s/(.)/sprintf("%%%02x",ord($1))/eg;
if($server !~ /:[0-9]{2,5}$/){$server.=":$port";}

for($i = 0; $i < 10; $i++)
{ 
 @temp = get_request($server,"search?filter=0&num=100&start=".$i.
 "00&q=$search") =~ /(https?\:\/\/[a-z0-9\.\-\/\?\:\&\%\=\_]{5,})/gi;
 
 $a = 0;
 foreach $url (@temp)
 {
   if($url =~ /https?\:\/\/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/search\?q=cache:/i){ next; }
   ($domain) = $url =~ /^https?\:\/\/([a-z0-9\.\-]{5,})/i;
   $f=0;foreach(@dn){if($_ eq $domain){$f++;last;}}if($f){next;}
   push(@found, $url);
   if($count){if(!--$count){$a++;last;}}
   push(@dn,$domain);
 }
 if($a){last;}
}

foreach(@found){print "$_\n";}

sub get_request()
{
 local $sock;
 local $data = "";
 local($server, $url) = ($_[0], $_[1]);
 $sock = IO::Socket::INET->new($server) or return -2; # connection failed
 print $sock "GET /$url HTTP/1.0\r\n\r\n";
 while(<$sock>){$data .= $_;}
 close $sock;
 return $data;
}

sub usage()
{

 print qq(
drmist's google parser v 0.8

usage: gparse.pl [-s <server>] [-p <port>] -r <request> [-n <number>]
 <server>  google server, default: google.com
 <port>    http-server port, default: 80
 <requets> search request
 <number>  number of links, that will be shown, default: all
examples:
 perl gparse.pl -r 'filetype:php inurl:page=' | grep page=
 perl gparse.pl -s google.ru:80 -r 'Powered by phpbb' -n 10
 perl gparse.pl -s google.ru -p 80 -r 'site:com inurl:backup.sql'
 perl gparse.pl -s google.de -r 'inurl:seite=' -n 400
   
for more information visit www.security-teams.net
 
);

}

Регулярки я думаю видны невооруженным глазом :)
Для PHP pcre-регулярки насколько я помню - например через preg_match_all
 
Вот ТУТ можно нормально прочитать о том как работают регулярные выражения.

Например вот так вот будут найдены ВСЕ (для preg_match будут найдено только первое) вхождения подстроки из шаблона, а так же подшаблонов. Они будут находиться в многомерном массиве который указывается в параметрах. Функция возвращает количество найденных вхождений.
Для создания подшаблонов в шаблоне используются скобки круглые, для указания произвольного символа - точка, поэтому частая ошибка - не экранирование левым слешем в шаблоне тех точек что там уже есть.

Как сделать шаблон? Все очень просто - берется кусок текста в котором содержится искомое. Это искомое делается подшаблоном например так: (.+), а все остальное оставляешь как есть, экранируя спец символы. если там что то може меняться то переменные куски строк заменяешь на .+ например. По крайней мере это самый простой способ :)
 
Вот я сам попробовал написать что бы получало все линки с главной страницы яндекса

Код:
<?php
$f = file_get_contents('http://yandex.ru/index.html');
preg_match_all("/<a href=\"(.*)\">(.*)<\/a>/", $f, $matches_art, PREG_PATTERN_ORDER);
echo $matches_art[1][ 0];
?>

Но вот что то не работает, в чём мая ошибка?
 
Потому что echo $matches_art[1][ 0]; выводит первую ссылку. Если хочешь понять структуру - замени это на print_r($matches_art);

Кстати о
после десятка серчей гугл забанит твой айпи
Вполне реально парсить с полминутной задержкой (актуально только для обычных запросов, без всяких inurl, intext и пр.)
 
DiegO, я же ссылку дал. Вот то же, но на русском.

Кстати насчет бана - там же не бан, просто капчу ввести просят, насколько я помню? :)
 
Думаю что ошибка в следующем:
preg_match_all("/<a href=\"(.*)\">(.*)<\/a>/", $f, $matches_art, PREG_PATTERN_ORDER);
ты тут в качестве ограничителей используешь правый слешь, и его же используешь в выражении, в силу каких то ебических причин это не допустимо. Вот так будет работать:
preg_match_all("|<a href=\"(.+)\">(.+)<\/a>|Ums", $f, $matches_art, PREG_PATTERN_ORDER);

Сделай print_r($matches_art); чтоб посмотреть что нашлось. Не забывай про модификаторы мультистрок, об этом есть в статье что я дал.
 
там же не бан, просто капчу ввести просят
да, только она тоже мешает парсингу :)

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

DiegO, учти, что у тега A может быть что-то кроме href'а
 
Вот как я понял доложно быть так [/CODE]<?php
$f = file_get_contents('http://yandex.ru/');
preg_match_all("|<a href=\"(.*?)\">(.*?)<\/a>|Ums", $f, $matches_art, PREG_PATTERN_ORDER);
print_r($matches_art);
?>
Код:
Но не катит, выводится где то ссылками где то нект, выводит картинки, и ещё много разной херни и ещё выводит Array - вообщем попробуйте сами...
 
Код:
<?php
$f = file_get_contents('http://yandex.ru/yandsearch?text=%D1%85%D0%B5%D1%80%D0%BD%D1%8F&lr=5');
preg_match_all('|.+<a.+href="([^"]+)"[^>]*>([^<]+)</a>.+|Ums', $f, $matches_art);
echo "Урлы:\n";
print_r($matches_art[1]);
echo "Названия:\n";
print_r($matches_art[2]);
?>

Вот что выдает:
Урлы:
Array
(
[0] => //m.yandex.ru/search?query=%D1%85%D0%B5%D1%80%D0%BD%D1%8F
[1] => //mail.yandex.ru
[2] => //maps.yandex.ru
[3] => //market.yandex.ru
[4] => //news.yandex.ru
[5] => //slovari.yandex.ru
[6] => //blogs.yandex.ru
[7] => //video.yandex.ru
[8] => //images.yandex.ru
[9] => //auto.yandex.ru
[10] => //afisha.yandex.ru
[11] => //money.yandex.ru
...

Названия:
Array
(
[0] => Мобильная версия
[1] => Почта
[2] => Карты
[3] => Маркет
[4] => Новости
[5] => Словари
[6] => Блоги
[7] => Видео
[8] => Картинки
[9] => Авто
 
preg_match_all("|<a href=\"(.*?)\">(.*?)<\/a>|Ums", $f, $matches_art, PREG_PATTERN_ORDER);
Использовать надо либо .*? без U, либо .* вместе с U

preg_match_all('|.+<a.+href="([^"]+)"[^>]*>([^<]+)</a>.+|Ums', $f, $matches_art);
Это наиболее правильно, но не понятно начинающему, ага (и если на то пошло, после a заменить . на [^>]). Один вопрос только: зачем по краям .+, ведь оно неправильно отработает для двух ссылок, идущих подряд?
 
неправильно отработает для двух ссылок, идущих подряд?
Это детали :) на яндексе вроде нет таких... можно поставить конечно .* на концах регулярки, это избавляет от жадности :)
А раньше проблемы были не только в этом у ТС - а именно с синтаксисом выражения.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх