2008-10-13 11 views
23

Estoy buscando una biblioteca que tenga una funcionalidad similar a la de Perl WWW::Mechanize, pero para PHP. Básicamente, debería permitirme enviar solicitudes HTTP GET y POST con una sintaxis simple, y luego analizar la página resultante y devolver en un formato simple todos los formularios y sus campos, junto con todos los enlaces en la página.¿Hay un equivalente PHP de WWW :: Mechanize de Perl?

que sé sobre CURL, pero es un poco demasiado barebones, y la sintaxis es bastante feo (toneladas de curl_foo($curl_handle, ...) declaraciones

Aclaración:

quiero algo más alto nivel de las respuestas hasta . Por ejemplo ahora, en Perl, usted podría hacer algo como:

# navigate to the main page 
$mech->get('http://www.somesite.com/'); 

# follow a link that contains the text 'download this' 
$mech->follow_link(text_regex => qr/download this/i); 

# submit a POST form, to log into the site 
$mech->submit_form(
    with_fields  => { 
     username => 'mungo', 
     password => 'lost-and-alone', 
    } 
); 

# save the results as a file 
$mech->save_content('somefile.zip'); 

para hacer lo mismo usando HTTP_Client o wget o curl serían mucho trabajo, que tendría que analizar manualmente t él busca los enlaces, encuentra el URL del formulario, extrae todos los campos ocultos, y así sucesivamente. La razón por la que estoy pidiendo una solución de PHP es que no tengo experiencia con Perl, y probablemente podría construir lo que necesito con mucho trabajo, pero sería mucho más rápido si pudiera hacer lo anterior en PHP.

+0

Realmente * es * un puerto de eso: http://www.compasswebpublisher.com/php/www-mechanize-for-php pero es parte de algunos CMS y no hay descarga. – Gordon

Respuesta

21

de SimpleTest ScriptableBrowser se puede utilizar independendly del marco de pruebas. Lo he usado para numerosos trabajos de automatización.

+0

Esto se ve bastante bien, tendré que intentarlo. Tiene casi todo lo que necesitaría, lo único que falta es una manera de enumerar todos los enlaces/formularios en una página, pero creo que podría hacerlo. – davr

+0

Puede usar $ browser-> getUrls(). De lo contrario, siempre puede usar $ dom = DomDocument :: loadHtml ($ browser-> getContent()), y luego $ dom-> getElementsByTagName ("a"), si necesita más control. – troelskn

1

Intente buscar en la biblioteca PEAR. Si todo lo demás falla, crea un contenedor de objetos para curl.

Puede por lo que algo tan simple como esto:

class curl { 
    private $resource; 

    public function __construct($url) { 
     $this->resource = curl_init($url); 
    } 

    public function __call($function, array $params) { 
     array_unshift($params, $this->resource); 
     return call_user_func_array("curl_$function", $params); 
    } 
} 
+0

Esto no es exactamente lo que estoy buscando, agregué una aclaración que espero que sea más clara, gracias. – davr

1

Pruebe uno de los siguientes:

(Sí, es código ZendFramework, pero no hace que tu clase sea más lenta usándolo, ya que solo carga las libs necesarias.)

+0

Todavía son mucho más trabajo que Mechanize, consulte mi aclaración a la pregunta. – davr

+0

Buena Q. Creo que ninguno de ellos lo hace todavía. Pero creo que estaría listo para construirlo, voy a ver la API de Mechanize mañana. – Till

+0

Si terminas haciendo algo, por favor publica una nueva respuesta y definitivamente voy a echarle un vistazo. Es posible que desee ver la respuesta 'ScriptableBrowser' como punto de partida, creo que solo necesita unas cuantas características más para hacer todo lo que Mechanize hace. – davr

-1

Si está en un sistema * nix puede usar shell_exec() con wget, que tiene muchas opciones agradables.

+1

Oh, bueno, sí, no lanzaría la entrada del usuario allí mismo. –

1
+0

Parece interesante, pero es bastante viejo (última actualización de 2005), y aunque es mejor que curl/wget, le faltan algunas características que lo harían más agradable. – davr

1

Curl es el camino a seguir para las solicitudes simples. Funciona multiplataforma, tiene una extensión PHP y es ampliamente adoptado y probado.

He creado una buena clase que PUEDE OBTENER y PUBLICAR una serie de datos (¡INCLUYENDO ARCHIVOS!) A una url simplemente llamando a CurlHandler :: Get ($ url, $ data) || CurlHandler :: Post ($ url, $ data). Hay una opción de autenticación de usuario de HTTP opcional también :)

/** 
* CURLHandler handles simple HTTP GETs and POSTs via Curl 
* 
* @package Pork 
* @author SchizoDuckie 
* @copyright SchizoDuckie 2008 
* @version 1.0 
* @access public 
*/ 
class CURLHandler 
{ 

    /** 
    * CURLHandler::Get() 
    * 
    * Executes a standard GET request via Curl. 
    * Static function, so that you can use: CurlHandler::Get('http://www.google.com'); 
    * 
    * @param string $url url to get 
    * @return string HTML output 
    */ 
    public static function Get($url) 
    { 
     return self::doRequest('GET', $url); 
    } 

    /** 
    * CURLHandler::Post() 
    * 
    * Executes a standard POST request via Curl. 
    * Static function, so you can use CurlHandler::Post('http://www.google.com', array('q'=>'StackOverFlow')); 
    * If you want to send a File via post (to e.g. PHP's $_FILES), prefix the value of an item with an @ ! 
    * @param string $url url to post data to 
    * @param Array $vars Array with key=>value pairs to post. 
    * @return string HTML output 
    */ 
    public static function Post($url, $vars, $auth = false) 
    { 
     return self::doRequest('POST', $url, $vars, $auth); 
    } 

    /** 
    * CURLHandler::doRequest() 
    * This is what actually does the request 
    * <pre> 
    * - Create Curl handle with curl_init 
    * - Set options like CURLOPT_URL, CURLOPT_RETURNTRANSFER and CURLOPT_HEADER 
    * - Set eventual optional options (like CURLOPT_POST and CURLOPT_POSTFIELDS) 
    * - Call curl_exec on the interface 
    * - Close the connection 
    * - Return the result or throw an exception. 
    * </pre> 
    * @param mixed $method Request Method (Get/ Post) 
    * @param mixed $url URI to get or post to 
    * @param mixed $vars Array of variables (only mandatory in POST requests) 
    * @return string HTML output 
    */ 
    public static function doRequest($method, $url, $vars=array(), $auth = false) 
    { 
     $curlInterface = curl_init(); 

     curl_setopt_array ($curlInterface, array( 
      CURLOPT_URL => $url, 
      CURLOPT_RETURNTRANSFER => 1, 
      CURLOPT_FOLLOWLOCATION =>1, 
      CURLOPT_HEADER => 0)); 
     if (strtoupper($method) == 'POST') 
     { 
      curl_setopt_array($curlInterface, array(
       CURLOPT_POST => 1, 
       CURLOPT_POSTFIELDS => http_build_query($vars)) 
      ); 
     } 
     if($auth !== false) 
     { 
       curl_setopt($curlInterface, CURLOPT_USERPWD, $auth['username'] . ":" . $auth['password']); 
     } 
     $result = curl_exec ($curlInterface); 
     curl_close ($curlInterface); 

     if($result === NULL) 
     { 
      throw new Exception('Curl Request Error: '.curl_errno($curlInterface) . " - " . curl_error($curlInterface)); 
     } 
     else 
     { 
      return($result); 
     } 
    } 

} 

?> 

[editar] Leer la aclaración sólo ahora ... Es posible que desee ir con una de las herramientas mencionadas anteriormente que automatiza cosas. También puede optar por utilizar una extensión de Firefox para clientes como ChickenFoot para mayor flexibilidad. Dejaré la clase de ejemplo de arriba para futuras búsquedas.

+0

Gracias por el ejemplo, creo que este tipo de envoltorio puede ser útil para otras tareas, pero sí, lo que debería haber dejado más claro al principio es que quiero un tipo de automatización – davr

2

Me siento obligado a responder a esto, a pesar de que es una publicación anterior ...He estado trabajando con PHP Curl mucho y no es tan bueno en cualquier lugar comparable a algo como WWW: Mechanize, que estoy cambiando (creo que voy a ir con la implementación del lenguaje de Ruby) .. Curl está desactualizado como requiere mucho "trabajo arduo" para automatizar cualquier cosa, el navegador de secuencias de comandos más simple me pareció prometedor, pero al probarlo, no funcionará en la mayoría de los formularios web en los que lo intento ... honestamente, creo que falta PHP esta categoría de raspado, automatización web así que es mejor mirar un idioma diferente, solo quería publicar esto ya que he pasado incontables horas sobre este tema y tal vez le ahorrará a alguien más en algún momento en el futuro.

1

Si está utilizando CakePHP en su proyecto, o si está inclinado a extraer la biblioteca relevante, puede utilizar su envoltorio de curl HttpSocket. Se tiene la sintaxis sencilla página-ir a buscar usted describe, por ejemplo,

# This is the sugar for importing the library within CakePHP  
App::import('Core', 'HttpSocket'); 
$HttpSocket = new HttpSocket(); 

$result = $HttpSocket->post($login_url, 
array(
    "username" => "username", 
    "password" => "password" 
) 
); 

... aunque no tiene una forma de analizar la página de respuesta. Para eso voy a usar simplehtmldom: http://net.tutsplus.com/tutorials/php/html-parsing-and-screen-scraping-with-the-simple-html-dom-library/ que se describe a sí mismo como una sintaxis similar a jQuery.

Tiendo a aceptar que la conclusión es que PHP no tiene las geniales bibliotecas de raspado/automatización que tiene Perl/Ruby.

2

Es 2016 ahora y hay Mink. Incluso admite diferentes motores, desde el "navegador" HP sin cabeza (sin JavaScript), a través de Selenium (que necesita un navegador como Firefox o Chrome) hasta un "browser.js" sin cabeza en NPM, que SOPORTA JavaScript.

+0

Esto es inmensamente útil y mucho mejor que todo lo demás mencionado en esta página. ¡Gracias por la actualización! – supersan

Cuestiones relacionadas