如果数据是通过Javascript加载的,如何使用php Goutte和Guzzle进行爬网?

时间:2016-04-17 07:04:01

标签: php web-crawler guzzle scraper goutte

很多时候,在抓取时我们会遇到问题,在这些问题中,使用Javascript生成页面上呈现的内容,因此scrapy无法抓取它(例如,ajax请求,jQuery)

4 个答案:

答案 0 :(得分:7)

你想看看phantomjs。有这个PHP实现:

http://jonnnnyw.github.io/php-phantomjs/

如果你当然需要使用php。

你可以阅读页面然后将内容提供给Guzzle,以便使用Guzzle给你的好功能(比如搜索内容等等)。这取决于你的需求,也许你可以简单地使用dom,如下:

How to get element by class name?

这是一些有效的代码。

  $content = $this->getHeadlessReponse($url);
  $this->crawler->addContent($this->getHeadlessReponse($url));

  /**
   * Get response using a headless browser (phantom in this case).
   *
   * @param $url
   *   URL to fetch headless
   *
   * @return string
   *   Response.
   */
public function getHeadlessReponse($url) {
    // Fetch with phamtomjs
    $phantomClient = PhantomClient::getInstance();
    // and feed into the crawler.
    $request = $phantomClient->getMessageFactory()->createRequest($url, 'GET');

    /**
     * @see JonnyW\PhantomJs\Http\Response
     **/
    $response = $phantomClient->getMessageFactory()->createResponse();

    // Send the request
    $phantomClient->send($request, $response);

    if($response->getStatus() === 200) {
        // Dump the requested page content
        return $response->getContent();
    }

}

只有使用幻像的缺点,它会比guzzle慢​​,但当然,你必须等待所有那些讨厌的js被加载。

答案 1 :(得分:2)

Guzzle(Goutte在内部使用)是一个HTTP客户端。因此,javascript内容将不会被解析或执行。驻留在请求端点之外的Javascript文件将不会被下载。

根据您的环境,我认为可以使用PHPv8(嵌入Google V8 javascript引擎的PHP扩展程序)和自定义handler / middleware来执行您想要的操作。

然后,根据您的环境,使用javascript客户端执行抓取可能更容易。

答案 2 :(得分:0)

我建议尝试获取响应内容。初始化新的Crawler对象时,将其解析(如有必要)为新的html,并将其用作$ html,之后,您可以像其他任何Crawler对象一样使用所有数据作为响应。

$crawler = $client->submit($form);
$html = $client->getResponse()->getContent();
$newCrawler = new Crawler($html);

答案 3 :(得分:-2)

由于无法使用javascript,我可以提出另一种解决方案:

  

GOOGLE CHROME>右键>检查元素>右键>编辑为html>复制>使用复制的html

        $html = $the_copied_html;
        $crawler = new Crawler($html);

        $data = $crawler->filter('.your-selector')->each(function (Crawler $node, $i) { 
                return [
                    'text' => $node->text()
                ];
        });

        //Do whatever you want with the $data
        return $data; //type Array

这仅适用于单个作业而非自动化流程。在我的情况下,这将做到这一点。