php抓取网页snoopy(如何在PHP中做到这一点,而不需要外部的“模拟器”)

优采云 发布时间: 2021-10-06 11:19

  php抓取网页snoopy(如何在PHP中做到这一点,而不需要外部的“模拟器”)

  您可以在 cURL 中执行此操作,而无需外部“模拟器”。

  以下代码会将页面检索到 PHP 变量中进行解析。

  脚本

  有一个页面(我们称之为 HOME)可以打开会话。在服务器端,如果是在 PHP 中,则是第一次调用 session_start()(实际上是任意一次)。在其他语言中,您需要一个特定页面来完成所有会话设置。从客户端,它是提供会话 ID cookie 的页面。在 PHP 中,所有会话页面都可以;在其他语言中,登录页面会这样做,其他人会检查cookie是否存在,如果不存在,则不会创建会话,您将被置于HOME。

  有一个页面(登录)会生成一个登录表单并添加一个带有关键信息的会话——“此用户已经登录”。在下面的代码中,这是需要会话 ID 的页面。

  最后,有N页,有好东西可以刮。

  所以我们要打HOME,然后登录,然后GOODIES一一。在 PHP(和其他语言)中,HOME 和 LOGIN 也可能是同一个页面。或者所有页面都可以共享相同的地址,例如在单个页面应用程序中。

  代码

   $url = "the url generating the session ID"; $next_url = "the url asking for session"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); // We do not authenticate, only access page to get a session going. // Change to False if it is not enough (you'll see that cookiefile // remains empty). curl_setopt($ch, CURLOPT_NOBODY, True); // You may want to change User-Agent here, too curl_setopt($ch, CURLOPT_COOKIEFILE, "cookiefile"); curl_setopt($ch, CURLOPT_COOKIEJAR, "cookiefile"); // Just in case curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $ret = curl_exec($ch); // This page we retrieve, and scrape, with GET method foreach(array( CURLOPT_POST => False, // We GET... CURLOPT_NOBODY => False, // ...the body... CURLOPT_URL => $next_url, // ...of $next_url... CURLOPT_BINARYTRANSFER => True, // ...as binary... CURLOPT_RETURNTRANSFER => True, // ...into $ret... CURLOPT_FOLLOWLOCATION => True, // ...following redirections... CURLOPT_MAXREDIRS => 5, // ...reasonably... CURLOPT_REFERER => $url, // ...as if we came from $url... //CURLOPT_COOKIEFILE => 'cookiefile', // Save these cookies //CURLOPT_COOKIEJAR => 'cookiefile', // (already set above) CURLOPT_CONNECTTIMEOUT => 30, // Seconds CURLOPT_TIMEOUT => 300, // Seconds CURLOPT_LOW_SPEED_LIMIT => 16384, // 16 Kb/s CURLOPT_LOW_SPEED_TIME => 15, // ) as $option => $value) if (!curl_setopt($ch, $option, $value)) die("could not set $option to " . serialize($value)); $ret = curl_exec($ch); // Done; cleanup. curl_close($ch);

  实现

  首先,我们必须获得登录页面。

  我们使用了一个特殊的用户代理来介绍自己,为了能够被识别(我们不想和网站管理员对抗),我们还欺骗服务器给我们发送定制版的浏览器< @网站。理想情况下,我们使用与要用于调试页面的任何浏览器相同的 User-Agent,并使用后缀来检查他们是否正在查看自动化工具(请参阅 Halfer 的评论)。

   $ua = 'Mozilla/5.0 (Windows NT 5.1; rv:16.0) Gecko/20100101 Firefox/16.0 (ROBOT)'; $cookiefile = "cookiefile"; $url1 = "the login url generating the session ID"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url1); curl_setopt($ch, CURLOPT_USERAGENT, $ua); curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiefile); curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiefile); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True); curl_setopt($ch, CURLOPT_NOBODY, False); curl_setopt($ch, CURLOPT_RETURNTRANSFER, True); curl_setopt($ch, CURLOPT_BINARYTRANSFER, True); $ret = curl_exec($ch);

  这将检索需要用户/密码的页面。通过检查页面,我们找到了必填字段(包括隐藏的字段)并可以填写它们。FORM 标签告诉我们是否需要继续 POST 或 GET。

  我们可能需要检查表单代码以调整以下操作,因此我们要求cURL将页面内容原样返回给$ret并返回页面正文。有时,将 CURLOPT_NOBODY 设置为 True 仍然足以触发会话创建和 cookie 提交,如果是这样,它会更快。但是 CURLOPT_NOBODY(“无正文”)发出 HEAD 请求而不是 GET。有时 HEAD 请求不起作用,因为服务器只会以完整的 GET 响应。

  除了以这种方式检索正文之外,您还可以使用真实的 Firefox 登录并嗅探使用 Firebug(或 Chrome 和 Chrome 工具)发布的表单内容;一些 网站 会尝试使用 Javascript 来填充/修改隐藏的字段,这样提交的表单就不会变成你在 HTML 代码中看到的表单。

  网站 管理员不希望他的 网站 被抓取,并且可能会发送一个带有时间戳的隐藏字段。一个人(没有太聪明的浏览器的帮助——有办法告诉浏览器不要太聪明;最坏的情况下,每次更改用户名并传递字段)至少需要三秒钟才能填写表格。cURL 脚本为零。当然,可以模拟延迟。这些都是太阳镜

  我们可能还需要注意表单的外观。例如,网站 管理员可以建立一个表单,询问姓名、电子邮件和密码;然后,通过使用 CSS,将“电子邮件”字段移动到要查找名称的位置,反之亦然。因此,实际提交的表单将在名为 username 的字段中收录“@”,但在名为 email 的字段中不收录“@”。服务端,期待这一点,正好将这两个字段颠倒过来。手工制作的“刮板”(或垃圾桶)会做一些看似自然的事情,并在电子邮件字段中发送电子邮件。这样做,它背叛了自己。通过真正的 CSS 和 JS 感知浏览器,发送有意义的数据,并嗅探发送的实际内容,我们也许能够克服这个特殊的障碍。也许,因为有办法让生活变得困难。正如我所说,太极拳。

  回到这个案例,在这个案例中,表单收录三个没有 Javascript 覆盖的字段。我们有 cPASS、cUSR 和 checkLOGIN,其值是“检查登录”。

  因此,我们准备了适当的字段表单。请注意,表单将用作 application/x-www-form-urlencoded,这在 PHP cURL 中意味着两件事:

  正如它所说,表单字段是 urlencoded;有一个功能。

  我们读取表单的 action 字段;这是我们将用于提交身份验证的 URL(我们必须这样做)。

  所以一切都准备好了

   $fields = array( 'checkLOGIN' => 'Check Login', 'cUSR' => 'jb007', 'cPASS' => 'astonmartin', ); $coded = array(); foreach($fields as $field => $value) $coded[] = $field . '=' . urlencode($value); $string = implode('&', $coded); curl_setopt($ch, CURLOPT_URL, $url1); //same URL as before, the login url generating the session ID curl_setopt($ch, CURLOPT_POST, True); curl_setopt($ch, CURLOPT_POSTFIELDS, $string); $ret = curl_exec($ch);

  我们现在期待着“你好,詹姆斯——下一场精彩的比赛怎么样?” 页。但更重要的是,我们期望与 $cookiefile 中保存的 cookie 关联的会话已经提供了关键信息——“用户已通过身份验证”。

  因此,所有后续使用 $ch 创建的页面请求和相同的 cookie jar 都将被授予访问权限,使我们能够非常轻松地“抓取”页面——记住将请求模式设置回 GET:

   curl_setopt($ch, CURLOPT_POST, False); // Start spidering foreach($urls as $url) { curl_setopt($ch, CURLOPT_URL, $url); $HTML = curl_exec($ch); if (False === $HTML) { // Something went wrong, check curl_error() and curl_errno(). } } curl_close($ch);

  在循环中,您可以访问 $HTML-每个页面的 HTML 代码。

  使用正则表达式的诱惑很大。你必须抵制它。为了更好地应对不断变化的 HTML,并且当布局保持不变但内容发生变化时(例如,您发现有 Nice、Tourrette-Levens、Castagniers,但从来没有 Asprémont 或 Gattières,是不是很奇怪?),最好的选择是使用 DOM:

  抓取A元素的href属性

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线