我想知道那一个更能接近浏览器获取网页内容的方式,在截取网页内容的时候经常浏览器可以正确打开的网站,用php的方法打开就会被block?现在网站都能判断出你是怎么来获得我网站内容的么?还是他们有什么机制可以得知?

解决方案 »

  1.   

    file_open_contents是fsockopen功能的简单打包  
    snoopy 是用fsockopen自开发的一个类curl 功能最强大,几乎可以模拟浏览器的各个方面,几乎可以以假乱真。
      

  2.   


    file_get_contents
    (PHP 4 >= 4.3.0, PHP 5)file_get_contents — 将整个文件读入一个字符串说明
    string file_get_contents ( string $filename [, bool $use_include_path [, resource $context [, int $offset [, int $maxlen ]]]] )
    和 file() 一样,只除了 file_get_contents() 把文件读入一个字符串。将在参数 offset 所指定的位置开始读取长度为 maxlen 的内容。如果失败,file_get_contents() 将返回 FALSE。 file_get_contents() 函数是用来将文件的内容读入到一个字符串中的首选方法。如果操作系统支持还会使用内存映射技术来增强性能。 Note: 如果要打开有特殊字符的 URL (比如说有空格),就需要使用 urlencode() 进行 URL 编码。 Note: context 参数可以用 NULL 来忽略。 
    更新日志
    版本 说明 
    5.0.0 添加了对 context 的支持。  
    5.1.0 添加了 offset 和 maxlen 参数。  
    注释
    Note: 此函数可安全用于二进制对象。Tip
    如已启用fopen 包装器,在此函数中, URL 可作为文件名。关于如何指定文件名详见 fopen()。各种 wapper 的不同功能请参见 支持的协议/封装协议列表,注意其用法及其可提供的预定义变量。Note: 在 PHP 5.0.0 中增加了 对上下文(Context)的支持。有关 上下文(Context) 的说明参见 Stream 函数。Warning
    使用 SSL 时,Microsoft IIS 会违反协议不发送close_notify标记就关闭连接。PHP 会在到达数据尾端时报告“SSL: Fatal Protocol Error”。要解决此问题,error_reporting 应设定为降低级别至不包含警告。 PHP 4.3.7 及更高版本可以在使用 https:// 包装器打开流时检测出有问题的 IIS 服务器软件 并抑制警告。在使用 fsockopen() 创建 ssl:// 套接字时, 开发者需检测并抑制此警告。
      

  3.   

    CURL简介
    PHP支持的由Daniel Stenberg创建的libcurl库允许你与各种的服务器使用各种类型的协议进行连接和通讯。libcurl目前支持http、https、ftp、gopher、telnet、dict、file和ldap协议。libcurl同时也支持HTTPS认证、HTTP POST、HTTP PUT、 FTP 上传(这个也能通过PHP的FTP扩展完成)、HTTP 基于表单的上传、代理、cookies和用户名+密码的认证。 这些函数在PHP 4.0.2中被引入。 
    snoopy 类
    snoopy是一个php类,用来模仿web浏览器的功能,它能完成获取网页内容和发送表单的任务。官方网站 http://snoopy.sourceforge.net/下面是它的一些特征:1、方便抓取网页的内容2、方便抓取网页的文字(去掉HTML代码)3、方便抓取网页的链接4、支持代理主机5、支持基本的用户/密码认证模式6、支持自定义用户agent,referer,cookies和header内容7、支持浏览器转向,并能控制转向深度8、能把网页中的链接扩展成高质量的url(默认)9、方便提交数据并且获取返回值10、支持跟踪HTML框架(v0.92增加)11、支持再转向的时候传递cookies
      

  4.   

    snoopy的缺陷与CURL的强大在使用PHP进行POST和GET的时候,如果为了简单的应用,大多情况下,我们都采用了fsockopen,于是snoopy就成了我们的最佳选择。可惜,并非所有POST都可以通过snoopy来完成。毕竟,在snoopy中,POST的方式,即类似FORM的entype只支持两种 :application/x-www-form-urlencoded和multipart/form-data,一个是针对FORM中的变量,一个是针对文件上传。一般来说这两种足够了。但昨天发现了一个问题。那就是http://www.baidu.com/search/blogsearch_help.html#n7
    baidu和google其他一样,都提供了blogsearch的ping服务,因此,你发表博客后,可以通知一下百度,你的博客更新了。
    于是昨天尝试着用snoopy来进行POST发送。结果一直失败,提示无法连接80端口,再看一下百度的说明:XML/HTML代码
    ping-service对非POST方法请求返回HTTP_METHOD_NOT_ALLOWED(405)错误代码,对超大错误包返回 HTTP_REQUEST_ENTITY_TOO_LARGE(413)错误代码,对非“text/xml”请求包返回 HTTP_UNSUPPORTED_MEDIA_TYPE(415)错误代码。  
    其他情况返回HTTP_OK(200)代码,xml-rpc响应http包体为一个xml文档,含有一个int值,0表示推送成功,其他值表示推送失败,目前只有0和1。  
    而snoopy在连接的时候是需要先fsockopen,打开80端口的连接后才能发送数据所以,死活连接不上了。最后,用了curl短短几行代码就解决了。。
    事实上,即使snoopy能够连接上百度的ping服务,也没有办法提交,因为$snoopy->submit()方法的第二个参数必须是数组。众所周知,FORM提交都是由name对应着value的。snoopy正是这样操作的,他无法直接把一个字符串不对应name就提交
      

  5.   


    只用过file_get_contents  其他没有用过,不过到现在这个我可以解决相当大的问题