Goutte - Web Crawler на PHP (паук)

Категория: PHP

Goutte - отличный инструмент для автоматизации серфинга по Web страницам из консоли или скрипта. Этот кроулер используется для автоматизации тестирования в таких PHP фреймворках, как Symfony 2 и Laravel 4. Он позволяет искать DOM элементы на странице, заполнять поля формы и отправлять форму, следовать по редиректу и изменять контент Web страницы. Goutte не выполняет JavaScript! Если вам это нужно - смотрите в сторону Selenium Web Driver, ZombieJS и прочих движков.

Документация:

Внимание!

Если внутри формы встречается следующая разметка, то Goutte не получает поля формы после тега input:

<script type="text/html">
  <input type="text" name="field"/>
  <div></div>
</script>

Если заменить script на div, или убрать вложенный div - все будет работать. Но все это явный баг.

Создал тикет: https://github.com/fabpot/Goutte/issues/155

Траверсинг

Получить DOM элемент содержащий текст:

$crawler->filter('h1:contains("Hello World!")')

Отфильтровать или изменить набор DOM узлов:

$templates = $crawler->filter('script[type="text/html"]');
$crawler = $templates->reduce(function (\Symfony\Component\DomCrawler\Crawler $node, $i) {
  $node->getNode(0)->setAttribute('class', 'some-class');
  return false; // false - исключить элемент из новой коллекции
});

Получить кнопку с текстом "Назад" и нажать на нее:

$link = $crawler->selectLink('Назад');
$this->assertCount(1, $link, 'На странице нет кнопки "Назад"');
$this->client->click($link->link());

Куки

Получить куки:

$cookieJar = $this->client->getCookieJar();

* Почему в getCookieJar() не возвращает куки SESSION_ID, laravel_session?

Пример теста с отправкой формы

// $btn = $form->selectLink('Добавить настройку'); // не работает

$url = URL::route('route_name', $id);

$crawler = $this->client->request('GET', $url);

// OR:
//$this->call('GET', $url);
//$crawler = $this->client->getCrawler();

$this->assertResponseOk();

// Проверить, что в шаблон передана переменная
$this->assertViewHas('sale_location');


$form_node = $crawler->filter('#id-name');
$this->assertCount(1, $form_node, 'На странице нет формы редактирования магазина');
$form = $form_node->form();

// filter() всегда возвращает объект
$btn = $form_node->filter('.class-name');
$this->assertCount(1, $btn, 'Нет кнопки "Добавить настройку"');

/** @var \Symfony\Component\DomCrawler\Field\ChoiceFormField $select */
$form['settings[type_id][0]']->select(1); // select option only by value

/** @var \Symfony\Component\DomCrawler\Field\ChoiceFormField $textarea */
$textarea = $form['settings[value][0]'];
$this->assertEquals('agnitas 123', $textarea->getValue());
$textarea->setValue('TEST');

// Set Form Data
$form->setValues(array(
  'settings[type_id][0]' => 1,
  'settings[value][0]'   => 'Some text',
));

$save_url = $form->getUri();
$method = $form->getMethod();
$values = $form->getValues();

$this->client->submit($form);
$crawler = $this->client->followRedirect(true);

$info = $crawler->filter('div.alert.alert-success');
$this->assertCount(1, $info, "Нет блока с сообщением об успешном сохранении");

// Check saved values
$crawler = $this->client->request('GET', $url);

$form_node = $crawler->filter('#sale_locations_form');
$field = $form_node->form()['settings[value][0]'];
$this->assertEquals('TEST', $field->getValue());

#goutte, #tdd, #crawler, #scraper, #traversing

категория: PHP