PHP采集利器snoopy应用详解

Snoopy是一个php类,用来模拟浏览器的功能,可以获取网页内容,发送表单。Snoopy正确运行需要你的服务器的PHP版本在4以上,并且支持PCRE(Perl Compatible Regular Expressions),基本的LAMP服务都支持。

一、Snoopy的一些特点:

1.抓取网页的内容 fetch

2.抓取网页的文本内容 (去除HTML标签) fetchtext

3.抓取网页的链接,表单 fetchlinks fetchform

4.支持代理主机

5.支持基本的用户名/密码验证

6.支持设置user_agent, referer(来路), cookies和header content(头文件)

7.支持浏览器重定向,并能控制重定向深度

8.能把网页中的链接扩展成高质量的url(默认)

9.提交数据并且获取返回值

10.支持跟踪HTML框架

11.支持重定向的时候传递cookies,要求php4以上就可以了,由于本身是php一个类,无需扩支持,服务器不支持curl时候的最好选择。

二、类方法:

fetch($URI)
———–

这是为了抓取网页的内容而使用的方法。$URI参数是被抓取网页的URL地址。抓取的结果被存储在 $this->results 中。如果你正在抓取的是一个框架,Snoopy将会将每个框架追踪后存入数组中,然后存入 $this->results。

fetchtext($URI)
—————

本方法类似于fetch(),唯一不同的就是本方法会去除HTML标签和其他的无关数据,只返回网页中的文字内容。

fetchform($URI)
—————

本方法类似于fetch(),唯一不同的就是本方法会去除HTML标签和其他的无关数据,只返回网页中表单内容(form)。

fetchlinks($URI)
—————-

本方法类似于fetch(),唯一不同的就是本方法会去除HTML标签和其他的无关数据,只返回网页中链接(link)。
默认情况下,相对链接将自动补全,转换成完整的URL。

submit($URI,$formvars)
———————-

本方法向$URL指定的链接地址发送确认表单。$formvars是一个存储表单参数的数组。

submittext($URI,$formvars)
————————–

本方法类似于submit(),唯一不同的就是本方法会去除HTML标签和其他的无关数据,只返回登陆后网页中的文字内容。

submitlinks($URI)
—————-

本方法类似于submit(),唯一不同的就是本方法会去除HTML标签和其他的无关数据,只返回网页中链接(link)。
默认情况下,相对链接将自动补全,转换成完整的URL。

三、类属性: (缺省值在括号里)

$host 连接的主机
$port 连接的端口
$proxy_host 使用的代理主机,如果有的话
$proxy_port 使用的代理主机端口,如果有的话
$agent 用户代理伪装 (Snoopy v0.1)
$referer 来路信息,如果有的话
$cookies cookies, 如果有的话
$rawheaders 其他的头信息, 如果有的话
$maxredirs 最大重定向次数, 0=不允许 (5)
$offsiteok whether or not to allow redirects off-site. (true)
$expandlinks 是否将链接都补全为完整地址 (true)
$user 认证用户名, 如果有的话
$pass 认证用户名, 如果有的话
$accept http 接受类型 (image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*)
$error 哪里报错, 如果有的话
$response_code 从服务器返回的响应代码
$headers 从服务器返回的头信息
$maxlength 最长返回数据长度
$read_timeout 读取操作超时 (requires PHP 4 Beta 4+)
设置为0为没有超时
$timed_out 如果一次读取操作超时了,本属性返回 true (requires PHP 4 Beta 4+)
$maxframes 允许追踪的框架最大数量
$status 抓取的http的状态
$temp_dir 网页服务器能够写入的临时文件目录 (/tmp)
$curl_path cURL binary 的目录, 如果没有cURL binary就设置为 false

四、以下是demo

include “Snoopy.class.php”;
$snoopy = new Snoopy;

$snoopy->proxy_host = “www.baidu.com“;
$snoopy->proxy_port = “8080”;

$snoopy->agent = “(compatible; MSIE 4.01; MSN 2.5; AOL 4.0; Windows 98)”;
$snoopy->referer = “http://www.baidu.com/“;

$snoopy->cookies[“SessionID”] = 238472834723489l;
$snoopy->cookies[“favoriteColor”] = “RED”;

$snoopy->rawheaders[“Pragma”] = “no-cache”;

$snoopy->maxredirs = 2;
$snoopy->offsiteok = false;
$snoopy->expandlinks = false;

$snoopy->user = “joe”;
$snoopy->pass = “bloe”;

if($snoopy->fetchtext(“http://www.baidu.com“))
{
echo ” <PRE>”.htmlspecialchars($snoopy->results).” </PRE>/n”; <BR>
} <BR>
else <BR>
echo “error fetching document: “.$snoopy->error.”/n”;

snoopy采集phpchina示例
<?php
//采集phpchina
set_time_limit(0);
require_once(“Snoopy.class.php”);
$snoopy=new Snoopy();
//登陆论坛
$submit_url = “http://www.phpchina.com/bbs/logging.php?action=login“;
$submit_vars[“loginmode”] = “normal”;
$submit_vars[“styleid”] = “1”;
$submit_vars[“cookietime”] = “315360000”;
$submit_vars[“loginfield”] = “username”;
$submit_vars[“username”] = “***”; //你的用户名
$submit_vars[“password”] = “*****”; //你的密码
$submit_vars[“questionid”] = “0”;
$submit_vars[“answer”] = “”;
$submit_vars[“loginsubmit”] = “提 交”;
$snoopy->submit($submit_url,$submit_vars);
if ($snoopy->results)
{
//获取连接地址
$snoopy->fetchlinks(“http://www.phpchina.com/bbs“);
$url=array();
$url=$snoopy->results;
//print_r($url);
foreach ($url as $key=>$value)
{
//匹配http://www.phpchina.com/bbs/forumdisplay.php?fid=156&sid=VfcqTR地址即论坛板块地址
if (!preg_match(“/^(http:////www/.phpchina/.com//bbs//forumdisplay/.php/?fid=)[0-9]*&sid=[a-zA-Z]{6}/i”,$value))
{
unset($url[$key]);
}
}
//print_r($url);
//获取到板块数组$url,循环访问,此处获取第一个模块第一页的数据
$i=0;
foreach ($url as $key=>$value)
{
if ($i>=1)
{
//测试限制
break;
}
else
{
//访问该模块,提取帖子的连接地址,正式访问里需要提取帖子分页的数据,然后根据分页数据提取帖子数据
$snoopy=new Snoopy();
$snoopy->fetchlinks($value);
$tie=array();
$tie[$i]=$snoopy->results;
//print_r($tie);
//转换数组
foreach ($tie[$i] as $key=>$value)
{
//匹配http://www.phpchina.com/bbs/viewthread.php?tid=68127&amp;extra=page%3D1&amp;page=1&sid=iBLZfK
if (!preg_match(“/^(http:////www/.phpchina/.com//bbs//viewthread/.php/?tid=)[0-9]*&amp;extra=page/%3D1&amp;page=[0-9]*&sid=[a-zA-Z]{6}/i”,$value))
{
unset($tie[$i][$key]);
}
}
//print_r($tie[$i]);
//归类数组,将同一个帖子不同页面的内容放一个数组里
$left=”;//连接左边公用地址
$j=0;
$page=array();
foreach ($tie[$i] as $key=>$value)
{
$left=substr($value,0,52);
$m=0;
foreach ($tie[$i] as $pkey=>$pvalue)
{
//重组数组
if (substr($pvalue,0,52)==$left)
{
$page[$j][$m]=$pvalue;
$m++;
}
}
$j++;
}
//去除重复项开始
//$page=array_unique($page);只能用于一维数组
$paget[0]=$page[0];
$nums=count($page);
for ($n=1;$n <$nums;$n++)
{
$paget[$n]=array_diff($page[$n],$page[$n-1]);
}
//去除多维数组重复值结束
//去除数组空值
unset($page);
$page=array();//重新定义page数组
$page=array_filter($paget);
//print_r($page);
$u=0;
$title=array();
$content=array();
$temp=”;
$tt=array();
foreach ($page as $key=>$value)
{
//外围循环,针对一个帖子
if (is_array($value))
{
foreach ($value as $k1=>$v1)
{
//页内循环,针对一个帖子的N页
$snoopy=new Snoopy();
$snoopy->fetch($v1);
$temp=$snoopy->results;
//读取标题
if (!preg_match_all(“/ <h2>(.*) <//h2>/i”,$temp,$tt))
{
echo “no title”;
exit;
}
else
{
$title[$u]=$tt[1][1];
}
unset($tt);
//读取内容
if (!preg_match_all(“/ <div id=/”postmessage_[0-9]{1,8}/” class=/”t_msgfont/”>(.*) <//div>/i”,$temp,$tt))
{
print_r($tt);
echo “no content1”;
exit;
}
else
{
foreach ($tt[1] as $c=>$c2)
{
$content[$u].=$c2;
}
}
}
}
else
{
//直接取页内容
$snoopy=new Snoopy();
$snoopy->fetch($value);
$temp=$snoopy->results;
//读取标题
if (!preg_match_all(“/ <h2>(.*) <//h2>/i”,$temp,$tt))
{
echo “no title”;
exit;
}
else
{
$title[$u]=$tt[1][1];
}
unset($tt);
//读取内容
if (!preg_match_all(“/ <div id=/”postmessage_[0-9]*/” class=/”t_msgfont/”>(.*) <//div>/i”,$temp,$tt))
{
echo “no content2”;
exit;
}
else
{
foreach ($tt[1] as $c=>$c2)
{
$content[$u].=$c2;
}
}
}
$u++;
}
print_r($content);
}
$i++;
}
}
else
{
echo “login failed”;
exit;
}
?>

snoopy.class.php php模拟登陆

官方网站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

下面是简单的例子,比如说我们抓取我的blog的文字

 

  1. <?
  2. include “Snoopy.class.php”;
  3. $snoopy = new Snoopy;
  4. $snoopy->fetchtext(“http://www.phpobject.net/blog”);
  5. echo $snoopy->results;
  6. ?>
  7. ^_^,不错把,在比如抓取链接
  8. <?
  9. include “Snoopy.class.php”;
  10. $snoopy = new Snoopy;
  11. $snoopy->fetchlinks(“http://www.phpobject.net/blog”);
  12. print_r($snoopy->results);
  13. ?>
  14. --------------------
  15. <?phpinclude(“snoopy.class.php”);
  16. $snoopy = new Snoopy;
  17. // need an proxy?://
  18. $snoopy->proxy_host = “my.proxy.host”;
  19. $snoopy->proxy_port = “8080”;
  20. // set browser and referer:
  21. $snoopy->agent = “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”;
  22. $snoopy->referer = “http://www.jonasjohn.de/”;
  23. // set some cookies:
  24. $snoopy->cookies[“SessionID”] = ‘238472834723489’;
  25. $snoopy->cookies[“favoriteColor”] = “blue”;
  26. // set an raw-header:
  27. $snoopy->rawheaders[“Pragma”] = “no-cache”;
  28. // set some internal variables:
  29. $snoopy->maxredirs = 2;
  30. $snoopy->offsiteok = false;
  31. $snoopy->expandlinks = false;
  32. // set username and password (optional)//
  33. $snoopy->user = “joe”;
  34. snoopy->pass = “bloe”;
  35. // fetch the text of the website www.google.com:
  36. if($snoopy->fetchtext(“http://www.google.com”))
  37. {     // other methods: fetch, fetchform, fetchlinks, submittext and submitlinks
  38.         // response code:    print “response code: “.$snoopy->response_code.”<br/>\n”;
  39.         // print the headers:        print “<b>Headers:</b><br/>”;
  40.     while(list($key,$val) = each($snoopy->headers))
  41.     {
  42.        print $key.”: “.$val.”<br/>\n”;
  43.     }
  44.      print “<br/>\n”;
  45.         // print the texts of the website:    print “<pre>”.htmlspecialchars($snoopy->results).”</pre>\n”;
  46.     }
  47.     else
  48.      {    print “Snoopy: error while fetching document: “.$snoopy->error.”\n”;
  49. }
  50. ?>

--------------------------------

首先,我们要获取到登陆需要发送什么字段,目标地址是什么。这里我们使用snoopy的fetchform来实现。

 

  1. <?
  2. include “Snoopy.class.php”;
  3. $snoopy = new Snoopy;
  4. $snoopy->fetchform(“http://www.phpx.com/happy/logging.php?action=login”);
  5. print $snoopy->results;
  6. ?>

当然你也可以直接查看http://www.phpx.com/happy/…的源代码来实现,不过这样更加方便把。这里,我们获取到目标和提交的数据,下一步就可以实现模拟登陆了。代码如下:

  1. <?
  2. include “Snoopy.class.php”;
  3. $snoopy = new Snoopy;
  4. $submit_url = “http://www.phpx.com/happy/logging.php?action=login”;
  5.      $submit_vars[“loginmode”] = “normal”;
  6.      $submit_vars[“styleid”] = “1”;
  7.      $submit_vars[“cookietime”] = “315360000”;
  8.      $submit_vars[“loginfield”] = “username”;
  9.      $submit_vars[“username”] = “********”; //你的用户名
  10.      $submit_vars[“password”] = “*******”;   //你的密码
  11.      $submit_vars[“questionid”] = “0”;
  12.      $submit_vars[“answer”] = “”;
  13.      $submit_vars[“loginsubmit”] = “提 &nbsp; 交”;
  14.      $snoopy->submit($submit_url,$submit_vars);
  15.      print $snoopy->results;
  16. ?>

为什么费用可能会超过您的每日预算

为什么费用可能会超过您的每日预算

AdWords 会关注搜索流量较高的日期,并在这些日期更频繁地展示您的广告,从而帮助您实现投资回报率最大化。如果发生这种情况,您每天的总费用最多可能会比通常的每日预算超出 20%,但是 AdWords 会根据月度费用限额,防止您当月的广告系列费用超支。

当广告系列费用超过每日预算时

如果您发现广告系列一天内的总费用超过了您的预算,这意味着您的广告系列在搜索流量较高的日期增加了预算,在搜索流量较低的日期减少了预算。这样,根据流量的波动情况,在一周内的某几天或每个月的某些时段,AdWords 可能会投入您每日广告系列预算的 120% 来展示您的广告,但您每个月的广告系列费用不会增加。

搜索流量的波动可能有以下几种原因:

  1. 周末或工作日
  2. 季节性变化和节假日
  3. 地缘政治和文化活动

借用当月其他日子的预算的做法有助于您的广告系列发挥最大潜力。然而,在费用超过 120% 的上限时,您仍然只需支付超出每日预算 20% 的部分。

例如,如果您的每日预算为每天 10 元,而您在某一天累积了 15 元的费用,则您只需支付 12 元。AdWords 使用月度费用限额来防止您意外超支。

月度费用限额

尽管广告系列费用在某一天可能会达到每日预算的 120%,不过,AdWords 采用了月度费用限额。只要您的预算在一整个月中保持不变,您支付的费用就不会超过每日预算金额乘以每月的平均天数所得到的值(按一年 365 天 ÷ 12 个月计算或每月 30.4 天)。

示例

如果您的预算在一整个月里都是每天 10 元,那么该月向您收取的费用最高为 304 元(每日预算 10 元 X 每月平均 30.4 天)。

如果您的预算在一整个月里始终保持不变,而您在一个日历月里累积的费用超过了您的月度限额所允许的金额,则我们只会按月度限额向您收费。例如,如果您的每日预算在一整个月中始终是每天 10 元(月度费用限额即为 304 元),而您在一个日历月里累积了 310 元的费用,那么您只需缴纳 304 元。

然而,如果您的每日预算在某个月份中发生了变化,我们将不会针对该月份使用月度费用限额(但 120% 的每日限额仍然有效)。

Cost per impression 俗称的 CPM 是什么?

http://en.wikipedia.org/wiki/Cost_per_impression

 

Cost per impression, often abbreviated to CPI or CPM (Cost per mille) are terms used in online advertising and marketing related to web traffic.[1] They refer to the cost of internet marketing campaigns where advertisers pay for every time their ad is displayed, usually in the form of a banner ad on a website, but can also refer to advertisements in Email advertising.

An impression is the display of an ad to a user while viewing a web page. A single web page may contain multiple ads. In such cases, a single pageview would result in one impression for each ad displayed.[2] In order to count the impressions served as accurately as possible and prevent fraud, an ad server may exclude certain non-qualifying activities such as page-refreshes or other user actions from counting as impressions. When advertising rates are described as CPM or CPI, this is the amount paid for every thousand qualifying impressions served.

Cost per mille is one of the most common marketing practice used on the internet along with Cost per click (CPC/PPC) and Cost per action (CPA) (including CPL and CPS). CPM advertising is often preferred by publishers because they can be more certain about the revenue they will generate from their website traffic. CPM can be compared with other marketing price strategies by examining their Effective cost per mille (eCPM). eCPM informs the publisher what they would have received if they sold the advertising inventory on a CPM basis by taking into account the Clickthrough rate (CTR) and/or Conversion rate (CVR) of the campaigns.

Cost per mille is the closest online advertising strategy to those offered in other media such as television or print, which sell advertising based on estimated viewership or readership. CPM provides a comparable measure to contrast internet advertising with other media.

[edit]See also

[edit]References

NVIDIA发布GeForce GTX670

同样基于Kepler架构,NVIDIA的全新一代次顶级产品GeForce GTX 670正式发布。NVIDIA为GTX670打了一个非常形象的比喻――相同的DNA,他们都采用了GK 104核心、同样2GB的GDDR5显存、同样的特色技术等等。

07254702006767569

GTX670显卡与GTX680采用了相同的GK104核心架构,只是GTX670核心代号为GK104-335,与GTX680采用的GK104-400有所区别,但两者全都是基于相同的Kepler架构。同时,GTX670也拥有相同的显存位宽与显存容量。

0725491546865382

当然,GTX670的规格自然不能与GTX680完全相同,在GTX670使用的GK104-335核心上通过削减一组SMX单元实现了与GK104-400核心的区别。同时,GTX670的运行频率也要比GTX680略低一些。GTX 670采用了阉割版的GK 104核心,拥有7组SMX也就是1344个CUDA核心,32个ROP单元,112个纹理单元,晶体管数量为3.54亿个。

月光博客:GODADDY疑似被封

原文:http://feedproxy.google.com/~r/letscorp/aDmw/~3/zfvSJtdCo4c/23849

今天,疑似Godaddy的又一组域名解析服务器(DNS)被封了,而这次被封带来严重的问题是,Godaddy自身的域名都已经无法解析了,使得中国用户无法访问。

经过测试,Godaddy的主站目前从中国地区解析很不稳定,使用ping命令测试,会发现经常出现无法解析域名的IP地址的情况出现。

从去年7月份开始,中国的一些电信运营商就开始屏蔽部分Godaddy的DNS服务,导致大量使用Godaddy的DNS的网站无法从中国访问,这种直接屏蔽NS(域名解析)服务的手法,影响非常恶劣,为了”惩罚”某一两个所谓的”有害信息”,直接导致成千上万的无辜网站无法访问,可谓”宁可错杀一千,不可放过一个”的极端手段。

3087_1

Godaddy是世界第一大域名注册商,Godaddy的域名注册费用是同行业中非常低,平均价格只有国内域名服务的一半,是一个非常不错的域名服务商,例如万网注册com域名要一年139元,Godaddy最低仅为50元。包括我在内的众多网站主都在使用Godaddy的域名注册服务。中国网络服务商对知名域名注册商的这种非法屏蔽涉嫌不正当竞争。

对于使用Godaddy注册域名的网站管理员,可以考虑暂时使用一些第三方的NS解析服务,目前有很多第三方网站提供DNS解析服务,不少都是免费的,国内也有免费提供DNS解析服务的,使用第三方DNS服务可以部分解决问题,电信总不可能将世界上所有DNS服务器都屏蔽掉。

不建议将Godaddy的域名迁移到国内,如果域名迁移到国内,那就不是屏蔽NS的问题了,而是直接clientHold,到时候就哭都来不及了。

PHP重要的安全更新:5.4.3 和 5.3.13

PHP 5.4.3/5.3.13紧急发布。2012-05-08 上个版本是2012-05-04的5.4.2/5.3.12修正CGI 相关漏洞,请尽快升级,mod_php 和php-fpm并不受影响。

Version 5.4.3

08-May-2012

  • Fixed bug #61807

    Buffer Overflow in apache_request_headers, CVE-2012-2329.

  • Fixed bug #61910 Improve fix for PHP-CGI query string parameter vulnerability, CVE-2012-2311.

Version 5.3.13

08-May-2012

  • Fixed bug #61910 Improve fix for PHP-CGI query string parameter vulnerability, CVE-2012-2311.

下载:http://cn.php.net/distributions/php-5.4.3.tar.bz2

http://cn.php.net/distributions/php-5.3.13.tar.bz2

用户体验优化的十个研究结果

网站用户体验优化的原理是什么?怎么样真正的把握住用户体验优化的要点,建议大家看看下文:

本文讨论一些用户可用性方面的研究发现,这些研究结果的获取,主要通过视觉轨迹、数据统计报告、以及关于网站可用性改进方面的调研。你将会发现,许多可用 性优化的提示是众所周知的,但是得到了更好的数据支持;与此同时,你也能得到一些惊喜,这些发现可能会改变你对目前网页设计方式发展走向的看法。

 

1、请忘记“三次点击定律”

这是一个历史悠久的说法:如果用户不得不点击三次以上才能找到他想要的内容,那么他会不耐烦并且有挫败感(而离去)。2001年,Jeffrey Zeldman–一个颇有名气的网页设计领域权威,在他的著作《Taking Your Talent to the Web》里提出,“三次点击定律”将帮助你的网站具备更有逻辑的层次和更符合直觉的访问感受。

逻辑上看,说的没错。用户在花了很多时间点击寻找所需内容以后,当然会烦躁。

但是为何要武断的设定“三次点击”的限制?是否有迹象显示,网站访客会在尝试了“三次”点击寻找以后就会忽然放弃?

事实上,大多数访客并不会因为他们点击了某个神秘的次数以后就放弃,点击的次数和他们是否烦躁并没有明显的关联。

一项由Joshua Porter在UIE(User Interface Engineering)网站发表的研究显示,用户经过更多次点击–例如十二次点击以后,并不比三次点击以后离去的趋势更明显。Porter提到,实际上几乎没有人因为点击了超过三次就放弃。

UX_001

留住用户的重点,不在于降低点击次数到某个神秘的数字以下,而是增加易用性本身。如果你能建立一个易用且带来愉悦的用户界面,但需要15次点击(5倍的“三次点击”)来完成某项工作,那么不要让无聊的三次点击定律限制了你自己。

 

2、运用F形模式来引导访客的内容浏览

Jakob Nielsen博士–一位可用性研究领域的先锋人士,曾组织超过230个参与者,进行了关于网页阅读习惯的视觉轨迹研究。这项研究结果显示,参与者在快速浏览网页时,视觉轨迹显示出F形的模式。(译者注:所谓F形模式,即从网页最左上看起,看完前面几行的大部分内容,越往下看的越短,形成F形浏览轨迹)

UX_002

另 一项由搜索引擎营销公司Enquiro and Did-it同视觉轨迹研究公司Eyetools合作开展的研究,采用相似的视觉轨迹研究方法,对50名参与者进行轨迹跟踪,结果证实了在参与者浏览 google搜索结果页面时,也出现F形模式。被称为“google金三角”的形成,正因为用户视觉的第一关注焦点是最左上部分,这个结果同 Nielsen博士研究提出的F形模式是相一致的。

UX_003

对网页设计师和网站写手来说,这些结果提示出,如果你希望内容更容易被看到,应该将其朝左放置,并且以符合F形状的形式来放置(例如标题后面跟段落摘要或关键字),这些都能增加用户快速浏览网页过程中看到这些内容的可能性。

 

3、不要让用户等待:加速你的网站

我们总是被告知用户是没有耐性的:他们讨厌等待。这很合理,谁喜欢特意去等呢?不过除了这些传闻以外,是否有切实的证据显示,用户不喜欢等待以及网页性能是否会影响到访客。

微软的搜索引擎-Bing进行了一项分析,研究页面载入速度和其他网站指标是否有明显的相关-如满意度、单位用户收入、点击速度等。报告显示,每2秒钟的页面延迟会降低3.8%的用户满意度,减少4.3%的单位用户收入和减少4.3%的点击数。对一个像微软那样规模的公司来说,4.3%的减少已经可以相当于数百万美元的损失。

UX_004

因此用户的“没有耐性”主要是因为他们等太久而不满,从而减少点击。此外如果你很在意搜索引擎排名,那么提升页面响应速度就显得更为迫切–google已经将页面速度加入了排名计算因素。

如何提升页面性能呢?使用各种工具来发现性能瓶颈,使用css sprites(译者注,将零散图片并成一个大图,来减少图片载入负载)提升页面速度,利用标准化度量工具如YSlow来协助进行前端性能优化。

 

4、让你的内容更容易阅读

Nielsen博士的一项关于用户在网页上阅读行为的研究提出,网络用户并不真正地在线阅读内容。他的分析显示用户仅仅阅读一个网页上28%的文字,并且这一数据还随着页面上文字总量的增加而进一步降低。UX_005

为了增加用户阅读到“大部分内容”的可能性,可以利用各种技术去使得内容更容易阅读。例如高亮显示关键字,标题,目录,缩短段落等。

 

5、不必担心页面下拉和滚动条

有一个古老的“神话”告诉我们,网页的重要内容必须要在“fold”(译者注:折叠线)上面,这是一个从报纸借到互联网的词汇,意思是无需滚动下拉条就能看到的页面区域,这个用法最早是由Jakob Nielsen提出的。

所以,很长的页面是否就糟糕呢?我们是否不得不把所有内容塞到页面顶部,因为用户不会去阅读“fold”以下–也就是需要下拉才能看到的内容呢?

一家网站分析公司Clicktale的报告给出的回答是:“并非如此”。这份报告结果显示,页面长度并不会影响到用户是否下拉浏览页面的可能性。

UX_006

另一份由用户导向设计公司CX Partners的Joe Leech的报告甚至提出,无需下拉即可看到区域的内容如果很少,反而可以激励用户下拉去探索更多的内容。

UX_007

这里需要重点指出的是,你无需因为害怕用户“不会下拉页面寻找”而将所有重要内容堆砌在页面顶部。正确的方法是,运用视觉分级原则和分区的技巧,来表现页面上各种内容的重要性和优先级(译者注:从而方便用户寻找内容,包括下拉寻找)。

 

6、将重要的网页内容靠左边放置

无论阅读还是写作,从小生活在“从左往右”书写的文化环境的人,都已经养成了从左边开始的习惯。这就是为什么大多数网页访客将主要注意力放在网页的左侧,根据Nielsen博士的涉及20余名用户的视觉轨迹研究报告指出,浏览左侧的“主要注意力”大约为69%的总浏览时间。

UX_008

同样的结果也从反面出现在那些“从右往左”书写的文化环境里,例如希伯来语或阿拉伯语的网站上,视觉轨迹报告的结果就正好相反(主要的注意力集中在右侧)。

从这个结果可以得到两件事。首先,你的网站界面设计需要考虑到包括语言、书写方向在内的诸多文化环境因素;其次,作为绝大多数的、从左往右阅读习惯的网站,将网页重要的元素放在左侧是一个好主意,反之亦然(从右往左阅读的网站,将重要元素放在右侧)。

 

7、文字之间的空间会影响可读性

有良好可读性的文字不仅容易理解,容易快速阅读,也能提升网站用户继续读下去–而不是关闭页面离开的可能性。影响可读性的因素有很多,包括字体选择(是否带衬线装饰),字体大小,行距,背景/前景对比度,以及文字之间的空间。

在一项关于可读性的研究测试中,20个参与者看到了内容完全一样的文字段落–不过文字边框的空间大小和行与行之间的距离不同。结果显示,没有边框空间的 文字读得更快,同时,理解效果降低了。当文字段落边上没有留空间时,阅读会加快,可以解释为文字之间靠得更近,目光从行到行、从段落到段落需要的时间更短。

UX_009

正如这个研究显示,我们对内容的设计样式会显著影响用户体验。保持对以下细节的关注:颜色、行距、分组,更进一步的还有所谓的网页排版技术,以此来保证你没有妨碍用户阅读网页内容。更多内容可以学习网页设计中的负空间设计。

 

8、微小的细节可以导致巨大的差异

当整个网页项目处于赶时间的状况时,经常发生只盯住大方面,而忽视一些小事的情况。时间或其他资源有限时,我们往往会放弃某些文字措辞的考虑,或者某个表格的按钮设计。有太多其他的事情需要我们考虑,一些小细节往往就随他去了。

不过有时,一些小细节–例如表格的某个按钮,会影响到整个网站的成功与否。在用户界面设计专家Jared Spool的一个案例中,他通过一个细节改动:在结算流程中移除一个按钮,换上一个更清晰的错误提示信息来防止用户操作失误,此改动在一年内提高了3亿美元的收入。第一个月,这个结算流程的改版直接带来了45%的销售额增长。

这种高度关注细节的做法得到了一家用户导向设计公司Flow的附和。他们发现通过修正网站的报错页面,来提供更有用的帮助文字,能提高每月成功结算率0.5%,推算出去,对这个网站意味着每年增加二十五万英镑的收入。

他们提供的“更有用”的帮助信息是什么?从一个不知所谓的404错误页面,变成一个礼貌的、两行的信息:“我们很抱歉,在处理您的订单时出现了错误。您的信用卡还未被付款,请点击结算再次进行付款。”

UX_010

关注细节,运用a/b对比测试来尝试和验证你的假设,从而寻找最有效的、能得到最优结果的设计。利用分析软件设定网站的目标,确定标杆,并且不断进行评估、测试、优化。

 

9、不要试图用搜索来弥补恶劣的导航设计

用户希望看到容易使用和组织良好的导航。即便有一个非常出色的站内搜索,用户仍然会首先使用主导航。根据Gerry McGovern进行的任务测试显示,超过70%的参与者在接到任务以后,首先是点击了页面上的一个链接,而不是使用搜索功能。

这个结果同UIE对30个用户进行的“电子商务任务测试”的结果很接近。研究分析指出,用户通常是在该页面的链接无法达到他们预期的情况下,才会转向到搜索引擎。也就是说,搜索只是被用在,当用户在当前页面不能找到他想找东西的情况下。

这些结果可以得出清晰的结论:不能依靠站内搜索来弥补或“拯救”差劲的内容组织、难以寻找、以及恶劣的信息架构等问题。当用户无法顺利被导航到他们想去的地方时,注意力应该转向界面设计、导航设计和内容组织的改进;至于改进搜索功能,则应作为次要因素。

 

10、你的首页并非你想的那样重要

访客来到你网站并不一定是首先到达首页。搜索引擎在这里是一个关键因素,他们将访客直接链接到你网站内的任何一个相关页面。其他网站的外部链接也是一样,经常直接链接到首页以外的,有相关内容的页面。

根据Gerry McGovern的分析,从网站首页进入的访客比例正在戏剧性地下滑。他见证了一个大型研究网站的“首页进入访客比例”从2003年的39%,下降到 2010年的2%。这一趋势在他研究的另一个网站也得到验证,首页进入访客比例在短短两年内减少了一半(从2008年的10%,下降到2010年的 5%)。

McGovern的研究结果表明,越来越多的流量来自于外部源头-搜索引擎、社会化媒体(如twitter)、内容聚合服务(如AllToP)–而不是 来自网站的首页。因此,将注意力从首页更多地转移到着陆页,将会为你的网站带来更高的性价比-花很少时间得到很大收获,以及更好的留住和转化用户的机会。

LNMP 一键安装 Linux Nginx MySQL PHP

LNMP 官方网站:http://lnmp.org/

安装

 

系统需求:

  • 需要2 GB硬盘剩余空间
  • 128M以上内存,OpenVZ的建议192MB以上(小内存请勿使用64位系统)
  • Linux下区分大小写,输入命令时请注意!

 

安装步骤:

1、使用putty或类似的SSH工具登陆;
登陆后运行:screen -S lnmp
如果提示screen命令不存在可以执行:yum install screen 或 apt-get install screen安装,详细的screen教程点击这里

2、下载LNMP一键安装包:
您可以选择使用下载版(推荐国外或者美国VPS使用)或者完整版(推荐国内VPS使用)
如需下载版执行命令:wget -c http://soft.vpser.net/lnmp/lnmp0.9.tar.gz
如需完整版执行命令:wget -c http://soft.vpser.net/lnmp/lnmp0.9-full.tar.gz
下载完成后LNMP一键安装包就会被下载到您的服务器或VPS上(一般用root登陆没切换目录的话应该在/root 下面)。

3、解压LNMP一键安装包:
执行:tar zxvf lnmp0.9.tar.gz 或 tar zxvf lnmp0.9-full.tar.gz 就会将LNMP一键安装包解压缩。

4、开始安装LNMP一键安装包:
进入LNMP安装目录,执行:cd lnmp0.9/ 或 cd lnmp0.9-full/
再执行安装程序前需要您确认您的Linux发行版,可以执行:cat /etc/issue 查看是CentOS、Debian还是Ubuntu,也可以通过VPS服务商提供的控制面板上查看。确定好之后,选择下面对应系统的安装命令:
CentOS系统下的安装
执行./centos.sh 2>&1 | tee lnmp.log
Debian系统下的安装
执行./debian.sh 2>&1 | tee lnmp.log
Ubuntu系统下的安装
执行./ubuntu.sh 2>&1 | tee lnmp.log
执行安装命令后,会出现如下界面:
lnmp-install-input-domain
输入要绑定的域名(建议使用一个二级域名,该域名会绑定到/home/wwwroot/,方便以后管理!如果输入有错误,可以按住Ctrl再按Backspace键删除),输入完成后回车,会显示如下界面:
(注:如果是Debian系统,输入域名后会提示Where are your servers located? asia,america,europe,oceania or africa,这里是选择服务器或VPS在哪个大洲,一般都是美国VPS,直接回车就行,如果是中国的,输入asia,回车。)
lnmp-install-input-mysql-root-password
再输入要设置的MySQL root的密码,输入完成后回车,会显示如下界面:
lnmp-install-input-mysql-innodb
如果需要安装InnoDB,可以输入 y 回车,不需要的话直接回车即可。回车后会显示如下界面:
lnmp-install-press
提示”Press any key to start…”,按回车键开始安装。
LNMP脚本就会自动安装编译Nginx、MySQL、PHP、phpMyAdmin、Zend Optimizer这几个软件。

5、安装完成
如果显示如下界面:
lnmp-install-success
说明已经安装成功。
如果显示如下界面:
lnmp-install-failed
说明没有安装成功!!需要用winscp到lnmp0.9的目录下找到lnmp.log,并下载下来,到LNMP支持论坛发帖注明你的系统、32位还是64位,并将lnmp.log以附件形式上传到论坛,我们会通过日志查找错误,并在帖子上进行反馈。

 

虚拟主机管理

lnmp-vhost

1、添加虚拟主机,执行如下命令:/root/vhost.sh 根据提示输入要绑定的域名,回车,如果需要添加更多的域名,输入y,再输入要另外绑定的域名,多个域名可以用空格隔开(注:带www和不带www的是不同的域名,如需带www和不带的www的域名都访问同一个网站需要同时都绑定)。再输入域名绑定的目录(绝对目录,如/home/wwwroot/lnmp,如果不填默认是/home/wwwroot/绑定的域名,目录不一定非要是/home/wwwroot/,如果/data/ 下面有大量的空间也可以填写/data/www/lnmp 之类的。),再选择是否添加伪静态规则,默认已经有了discuz、discuzx、wordpress、sablog、emlog、dabr、phpwind、wp2(二级目录wp伪静态),可直接输入以上名称即可,如果需要添加自定义伪静态规则,直接输入一个想要的名字,程序会自动创建伪静态文件,直接在/usr/local/nginx/conf/你自定义的伪静态名字.conf 里面添加伪静态规则就行(注:添加完执行/etc/init.)。接下来会提示是否需要启用日志功能,一般情况下不需要启动,直接输入n就行,如需启动,输入y,再输入要定义的日志文件名字,回车就会自动添加虚拟主机。

2、删除虚拟主机,ssh执行:rm /usr/local/nginx/conf/vhost/域名.conf

安装其他组件

(注:安装如下组件,必须在lnmp0.9的安装目录,即lnmp压缩包解压缩后cd lnmp0.9/后的目录!,如果找不到可以执行find / -name eaccelerator.sh查找。)
(注:以下组件不一定您都需要,请按您的需求使用!)

1、安装PureFTPd和FTP管理面板,执行如下命令:./pureftpd.sh 按提示输入你MySQL的root密码、FTP用户管理面板的密码、MySQl的FTP数据库密码(可直接回车,自动生成一个密码),回车确认,就会自动安装PureFTPd,提示安装完PureFTPd后,在浏览器执行http://你的域名或IP/ftp/ 输入你前面设置的FTP用户管理面板的密码,就可以管理FTP。

2、安装eAccelerator,执行如下命令:./eaccelerator.sh ,按提示选择版本,回车确认后,就会自动安装并重启web服务。

3、安装ionCube,执行如下命令:./ionCube.sh 回车确认后,就会自动安装并重启web服务。

4、安装imageMagick,执行如下命令:./imageMagick.sh 回车确认后,就会自动安装并重启web服务。

5、安装memcached,执行如下命令:./memcached.sh 回车确认后,就会自动安装并重启web服务。

升级程序

6、升级Nginx版本,执行如下命令:./upgrade_nginx.sh 按提示输入nginx的版本号,如1.0.10,版本号可以从http://nginx.org/en/download.html获取。(注:升级过程中MySQL、PHP-FPM将会暂停。)

7、升级PHP版本,执行如下命令:./upgrade_php.sh 按提示输入php版本号,如5.3.6。(注:某些网站程序,如shopex等有兼容性问题,升级前确保你使用的程序以支持5.3.*版本。升级过程中Nginx、MySQL、PHP-FPM将会暂停。)

状态管理

LNMP状态管理: /root/lnmp {start|stop|reload|restart|kill|status}
Nginx状态管理:/etc/init.d/nginx {start|stop|reload|restart}
PHP-FPM状态管理:/etc/init.d/php-fpm {start|stop|quit|restart|reload|logrotate}
PureFTPd状态管理: /etc/init.d/pureftpd {start|stop|restart|kill|status}
MySQL状态管理:/etc/init.d/mysql {start|stop|restart|reload|force-reload|status}
Memcached状态管理:/etc/init.d/memcached {start|stop|restart}

相关图形界面程序

phpinfo : http://前面输入的域名或IP/phpinfo.php
phpMyAdmin : http://前面输入的域名或IP/phpmyadmin/
探针 : http://前面输入的域名或IP/p.php
PureFTP管理界面:http://前面输入的域名或IP/ftp/
Memcached测试页面:http://前面输入的域名或IP/memcached.php

LNMP相关目录

nginx : /usr/local/nginx
mysql : /usr/local/mysql
php : /usr/local/php
网站目录: /home/wwwroot/
Nginx日志目录:/home/wwwlogs/
/root/vhost.sh添加的虚拟主机配置文件所在目录:/usr/local/nginx/conf/vhost/

LNMP相关配置文件

Nginx主配置文件:/usr/local/nginx/conf/nginx.conf
/root/vhost.sh添加的虚拟主机配置文件:/usr/local/nginx/conf/vhost/域名.conf
MySQL配置文件:/etc/my.cnf
PHP配置文件:/usr/local/php/etc/php.ini
php-fpm配置文件:/usr/local/php/etc/php-fpm.conf
PureFtpd配置文件:/usr/local/pureftpd/pure-ftpd.conf
PureFtpd MySQL配置文件:/usr/local/pureftpd/pureftpd-mysql.conf

 

注:LNMP一键安装包 0.9 & LNMPA已经在DiaHosting(感谢提供测试VPS)、VPSYOU(感谢提供测试VPS)、PhotonVPS(感谢提供测试VPS)、VPSZZLinodeXeHost瑞豪开源VPSYardVPSHostigationMyHost123ThrustVPSBuyVMDirectSpace等多家美国VPS的CentOS、Debian、Ubuntu的32位和64位系统上测试通过。(Debian5系统源目前有问题,请使用Debian6!小内存请勿使用64位系统)

王淮:我在Facebook的十点经验分享

我是2007年初加入Facebook, 那时大概150人; 2011年9月底离开, 当时3200多人. 经历了很多稀奇古怪但影响很大的项目, 像Application Platform, Social Ads, News Feed, Gift Shop, Facebook Credits等等. 碰到的很多的问题都是全新的, 规模是互联网历史上最大的. 当时的心惊肉跳现在回想起来是很让人怀念的旧时光. 到我离开Facebook的时候, 我负责支付安全和工具研发部门还有部分的支付后台研发组.

现在我在全职做天使投资, 给看对眼的团队在早期产品技术团队搭建给予一些力所能及的帮助. 有兴趣的朋友可以关注我的微博@王淮Harry哥.

在Facebook的这些年让我学习感悟了很多东西, 很多东西溶在血液中, 现在我换了时间来思考最值得分享的10点经验和大家分享. 希望能给创业的朋友一些启发.

在我们开始之前, 先来一段免责声明.

1- 这里所有的东西都是从我自己的亲身体会和实践中获得的. 不一定都是新的, 但都是真实的.

2- 所有的这些在Facebook的文化下能有效. 但不代表对你的公司一定有效. 好的种子还要有合适的土壤.

3- 不是所有的点都对你有用. 但有一点对你有用, 我就开心了.

OK. 我们开始吧.

1、坚持你的远见, 但灵活的把握细节

作为领导者, 在远见上你只有依靠自己, 至少在你自己负责的业务范围之内. 你是老板, 意味着整个公司; 你是经理, 意味着整个部门. 为你卖命的兄弟姐妹们是依靠你来给他们提供远见. 什么是远见? 就是对最终状态的一种描述。是让你的团队在疯狂的飞行之后最终着陆的地方。是辛辛苦苦忙忙碌碌之后的新生活。它是北极星,它来指明方向。举一个例子,当我一开始建立支付安全部门的时候,我们只有人工规则引擎. 规则是人写的. 一条人工规则是有少数变量的简单逻辑,比如“如果 (注册在30天之内 和 支出大于100美元 和 是首次支付 和 用户来自印度尼西亚),那么 (拒绝交易)” 但这里有个问题 – 人写的东西容易出错. 人很难有效的处理10个以上的变量. 我们需要一个更有可扩张性(scalable)的解决方案. 我们希望把很多事情自动化, 让机器人做更多机器擅长的事情。因此我们建立了一个共识 – 将我们绝大部分的规则逐步替换为机器学习获得的判断模型。这一远见让我们组新加了一位机器学习领域的博士和另一位之前有过机器学习体系开发经验的工程师。赌注巨大,但是一个更好的未来需要下这个注。

但你需要对细节灵活把握, 永远都有条条大路通罗马. 你需要给团队足够的空间来施展拳脚,只要他们在朝着正确的方向以合适的速度前进。另一个故事:在classification算法上一度我对决策树的兴趣比回归要大。但玩算法的工程师告诉它们之间的差别可以忽略。我可以坚持己见(当时我是真心觉得决策树要更合适)但我信任他并让他放手去选合适的算法。同设计师(Facebook的整个研发有设计师, 产品经理, 工程师三类物种) 合作的过程中也有趣事发生,他们对于字体,颜色,行距等等都很龟毛。我通常都会忍让, 只要服务于产品的主要功能。我们精力有限, 吵架要选择正确的战争,关乎全局的战争,而不是纠缠于某个局部战斗。

2 、只和最好的人合作

一流的牛人只愿意和牛人厮守。他们聚在一起会更牛逼。一流人才无法容忍二流的人. 那什么是“最好的人”?我的理解是能够尽其所知, 用其所长, 学其所不能, 从而迅速完成目标并远超期望. 他们的本能是挑战自己, 超越别人的期望,超越自己的期望. 对他们来说,仅仅足够好是不够好。

只有一流人才组成的团队有很多好处。

(1) 这让你更加愿意委托. 从我的经验来看, 牛人不会轻易信任不熟悉的人. 如果你还没有证明自己和他们一样出色甚至更出色, 他们宁愿自己独立工作劳累死也不愿接受你的帮助. 因为他们担心你会搞砸. 但当你证明自己之后, 他们会信任你, 放心的把事情交给你一起合作。一个互帮互助的牛逼团队才能做到1+1远大于2.

(2) 通过艰巨任务的完成牛人们互设榜样. 你会想”牛, 这哥们竟然能把这玩意做出来了, 咱得加油了”. 这种peer pressure合理的利用可以大幅度的提高工作表现并在团队中形成良性循环。

(3) 牛人们喜欢互相挑战. 我记得一位工程师总监立下赌约 – 如果我们在规定时限之前完成网站翻译平台所需的代码修改,他将把头发染成蓝色. 这样的挑战把“枯燥”的工作变成了挑战性游戏。在玩游戏中写程序比纯粹的写程序要有趣得多. 当然我们也有很多更加认真的挑战. 因为牛人们天生(贱命, 哈)容易对挑战上瘾, 不管是挑战别人还是接受挑战.

(4) 牛人们相互学到很多. 每个牛人都有自己牛的地方. 彼此有很多的互补. 如果Facebook不是有很多东西可以学习的话我不会呆4年多。对缺乏经验的人来说,这点很给力. 我们雇佣非常聪明的毕业生(潜在牛人),这些人希望引爆自己来证明他们的牛逼之处。他们不愿到一个舒适无挑战的公司过日复一日的生活。他们想学很多来丰富他们的经验,完成不可能完成的任务并在他们的职业生涯上前进。他们想要证明“yes, we can”。和其他牛人一起才能更容易的实现这些。

你不想要二流的人但如何远离他们?首先,慢点招人 (Hire Slow). 在招人的标准上固执一点. 训练你的面试人员让他们明白他们需要招(某些方面)比他们更强至少不会拖后腿的人, 如果不是, 拒绝平庸, 不要屈就. 我曾好几次在招聘决策会议上发现黄金履历者无法拿到Offer, 只因为某个面试官觉得这人无法给他深刻印象没有让他惊讶。但在另外一些例子当中,那些获得一致通过的候选人仍被放弃因为大家都只是觉得他仅仅符合要求而已, 没有出彩的地方. 在招人问题上,绝大多数情形下,你要小心不要冒进.(顺便提一下我们也会雇用那些没有全票通过的候选人, 只要有一两票是强烈推荐 – 因为对于已有员工的强烈推荐你是不应轻易忽视的, 这时可以冒险)其次,炒鱿鱼要快 (Fire Fast). 使用二流人才就像服用慢性毒药, 一天一点, 迟早咯屁. Facebook要求所有的管人经理对于员工的表现要特别敏感. 经理发现员工分配的任务或者答应的事情经常没有做到, 如果是客观原因, 一定要尽力帮助解决; 如果判断为人才质量为题, 走法律允许的程序迅速将人炒掉. 我见过几次炒的比较慢, 那对团队造成的负面作用可不是闹着玩的。

3、树立高的期望值并加以衡量

作为领导者,你需要设定足够高但仍合理的期望. 足够高使得你的团队不会感到无聊。仍合理使得他们不至于油尽灯枯。你要给他们创造一段经历使得在旅程结束时,他们回过头来看会说 – “他妹的, 我都没想到我居然做到了这个. 这个屌爆了.” 在Facebook, 和其他硅谷高技术公司一样,期望同薪酬相结合. 每半年Facebook都有5-6个公司级的大目标, 所有人的奖金算法中都会考虑该目标的完成情况. 因此树立明确的期望本身就至关重要。

另外, 你需要找到一个不容争辩的途径来衡量期望. 我花了大量时间和团队一起制定下季度里最重要的3-5个目标并有数据化的衡量指标 (一个目标背后可以有多个指标)。根据工作量把目标分别委派给单个或多个攻城狮,或者让他们自己揽。在这一情况下,我们不仅有可衡量的目标,使得我们可以迅速地说出来我们在做什么做到哪了,同时也知道每个具体目标后面的负责人是谁。团队的表现和个体表现挂钩, 所以他们失败了我即不成功. 例如, 当年我们团队最大的成果就是在一年时间里,通过每季度不同的指标,让信用卡支付的投诉率降低了75%.

有一点要强调的是﹣期望还是要基于现实要合理. 在你只有10%的市场份额的时候却幻想10几倍的收入增长无疑不现实. Steve Jobs乔老爷是这方面的老手, 非常善于推动他的团队超越潜能但同时也榨干他们(虽然他们后来还是为他们所做到的而自豪一辈子)99.9%的领导者不是乔老爷, 也不需要是。更可行的是在团队的真实极限中找到一个可持续性的驱动来激励团队超越自我.

4、重视数据而不盲从数据

决定产品方向时, 要的是想象力, 激情和胆量, 而不是数据. 数据能让你的团队沿着正确的方向前进而不出轨, 也有助于产品从“一开始是什么样”到“最后应该是什么样”的逐渐优化成型. 但数据不能帮你决定方向. 举个例子, 当我们在人工智能(机器学习)上压上我们团队所有的资源的时候, 我们忐忑不安. 但是我们坚信一点, 现有的基于人工规则引擎的防欺诈系统会很快成为死胡同, 因为它太死板而且不易规模化以处理大数据。所以, 就像在电影指环王中Frodo明知通向Mordor的道路很黑很冷很危险, 但那是一条他必须要选择去走的路; 我们选择了在机器学习上压上所有的宝。失败, 整个团队会很难看; 但我们决定走艰难但我们认为是正确的路. 这种思路同样应用在如何设计用于用户报告(外部工具)和案例审查(内部工具)的工具来应对潜在的欺骗行为。我们最后决定的方向是”进行自动处理”和”建立反馈机制”。直接抛给人工来处理总是很容易被选的一条路, 因为只要建立一个人多人傻的客户支持团队即可. Lame! 我们希望通过自动处理来解决大部分的欺诈案例,而把精力则放在那些确实需要单独处理的特殊案例上, 同时把从业务支持团队(即客户支持部门)的处理意见自动采集并集成到下一轮的机器学习中去。由此, 我们的机器判断会越加精确和聪明且与时俱进.

但你不能忽视数据。没有数据的支撑而一味靠直觉走黑路, 很容易走岔道, 甚至大错特错。有一段时间我们认为爬行工具(通过分析关联的cookie,信用卡)可能可以找到很多欺诈的同伙。通过实验结果却发现, 这种预期是否成立很大程度上取决于当前流行的欺诈行为的特点. 比如, 当失窃或贩卖信用卡的案例非常普遍的时候,关联分析是一种有效的方法。但如主要情况是帐户被黑或小宝们冒用妈妈的信用卡去网游消费时,关联分析就作用不大。直觉在现实前面碰了一脸的灰。不过幸运的是我们很快意识到这点且把这个项目叫停了, 所以没有浪费太多的资源。

另外, 顺带提一下A/B测试。A/B测试并不会告诉你去做什么产品,但它可以帮你确定实现产品时的哪个细微版本更能揪住用户大爷们的心。

5、避免无谓的时间浪费

刚进Facebook做工程师的时候,我非常享受那种日夜泡在码海中的感觉。后来慢慢的承担的项目责任越来越大越来越多,写代码的时间越来越少(但绝大多数时候仍占大头). 有时候更多的是把时间花在决定产品的方向和设计上。很多事情是和产品经理设计人员一起搞的. 但在Facebook攻城狮们有很大的发言权甚至有些时候是拍板的权力。Facebook希望攻城狮们有王者风范. Facebook希望攻城狮能决定自己要做什么应该做什么, 而不是总是”被决定”做什么(一种流行的说法是,write your own job description). 因此,我花了大量的时间在思考这些问题 – 哪些功能需要添加,哪些功能需要删掉,需要开始或停掉哪些测试,我们正在流血流汗的是不是现在最最最重要的问题, 我们是该花时间优化用户交互流程呢, 还是减少出错率, 还是让系统更快, 等等。这些问题很伤脑筋, 答案经常不确定, 比一个劲码到手抽筋要难. 但这些问题很重要, 甚至可能决定了你熬的日日夜夜究竟有没有必要. 建议所有的攻城狮思考思考代码之外的这些问题, 团队领导者就更有必要了. 当然, 攻城狮的大多数时间还是应该花在代码上.

那究竟哪些时间不应该被浪费呢?

很多, 但我只举两个我认为最重要的例子。

邮件。不是所有邮件都发而平等。有些邮件纯粹打酱油的. 有些邮件是不需要马上处理的. 我尝试使用过滤规则来踢掉打酱油的邮件, 突出需要马上处理的重要邮件。对此,分享两点。

1) 建立一个适合你的邮件过滤系统. 我会对重要和紧急的邮件做即刻回复,而暂缓处理那些可以等到晚上再回复的邮件(尤其是发自我自己的团队,产品经理,兄弟连和顶头的不顶头的上司们的邮件)。但是,我要确保在我挣扎的爬到床上之前,把这些邮件全部处理掉, 读的读, 回的回。对于那些仅供参考的邮件,过滤系统会将其塞到某个固定的角落,我隔三差五去瞅瞅。此类邮件诸如某酒鬼询问Napa Valley哪个酒窖比较正点等等. 这些邮件通常比较有趣, 挖的坑很大很深所以也很耗时间, 我通常不跳或者不马上跳。

2) 广而告之你的个人邮件处理策略. 我让我身边的战友们知道我是如何处理邮件的, 并把这个政策放到我所有的邮件末端。如是说 – “正在尝试个人邮件处理策略-为了戒掉Email瘾, 我将强迫自己每隔三小时或以上查看一次Email,急事请电话/短信/IM我” 这么做更多的是让别人明白不要指望马上得到回应. 其实我查email比每3小时要频繁, 但至少不用马上逼得去回每个email了, 我可以憋着悠着点. 因为如果真的很急, 我的iPhone应该已经响过了. 而且, 批量处理真的效率要高很多. 不骗你.

会议。开会太容易变成一群人互相在扯对方的蛋. 浪费时间而且开完后发现没有结论且很蛋疼. 但开会对于teamwork很多时候是必要的. 如何主持会议是门学问, 这里不细谈. 不过, 你不可能也不需要参加每个邀请你的会议。当你认为你参加某会议于己于人都无太多价值的时候, 建议你考虑不去。如果想要有礼貌一点, 那就写个email问问主持人你是否可以缺席. 通常当你想过这个问题决定发这样的邮件时,答案通常都会是yes。有些时候我也会很可耻的让我的产品经理替我去开会。当然,我会鼓励他也争取不要去。Only make the meetings you really have to. 同样, 我要求我自己的团队在组织和参加会议的时候要慎重,也经常问他们想想看自己花在会议上的时间是不是多了。一个做法是把可能的会议都整合在一起。有一个例子。早些时候, 我们会经常收到来自支持团队的比较随意的会面请求。这让攻城狮的一天被会议分割得支离破碎. 写代码的都知道没有3-4个小时的连续时间是不容易高潮的. 而且这种会议通常效率很低. 于是,我们改变了做法,每周安排固定的答疑时间(office hour)和支持团队嗑想法然后follow up。当然, 紧急的问题另当别论应当马上处理.

有一个被经常忽略的原则 – 有意识地去思考哪些事情不应该做并且马上不做。例如,哪些是无谓的争论可以避免介入,哪些功能可以放弃,哪些关系不应该发展, 哪些人应该开掉, 等等。我经常问自己一个很简单的问题,我现在正在做的是否对我的目标很重要。如果你清楚自己正在做的和自己想要的,答案会明了。Go for it。
6、增进亲密感是减少紧张关系的有效方式

工程师和支持团队之间有着纠结的合作竞争关系(注意, 合作在前)。互联网技术公司中很多人(尤其是聪明人)总是期望工程师对所有问题给出一个让人会心一笑的解决方案。但现实是,不是每一个问题都可以或者应该在技术框架下解决。对于一些具体的问题, 客户支持和运营部门会有一些非常深刻独到的见解. 工程师未必行. 毕竟很多见解需要不同的专业知识, 依靠实地经验。没错, 工程师可以在代码中自动log大量的原始数据,但从原始数据中提炼可靠的判断却并不总能如愿. 和很多其他公司的客户或支持部门不同, 我们的支持部门招募了质量相当好的员工(很多来自美国名校 – 在我直接接触的反欺诈支持组20来人中就有3名斯坦福校友)。因此,当两群都很聪明的人观点相左时,该听谁的呢? 紧张关系再所难免。

不同的工程师团队也存在着合作竞争关系。 反垃圾邮件、安全和反欺诈(我的团队)这几个团队之间存在密切的工作协作关系。这些团队也都尽可能地相互学习,分享经验和技术。但是,有时候各团队独立处理类似但不同的一些问题时,都试图向对方推销自己的解决方案和理念。

如何让合作竞争保持在一种健康有序的状态? 我觉得关键是促进人与人之间的亲密感。把人搞近了, 事情就容易了. 我花大量时间用在建立和其他团队的关系上面。例如两周一次或者一月一次和其他团队老大们的1对1碰头会。越相关的团队, 头碰得越频繁. 我自己或者我的团队成员会有选择性的经常参加一些其他团队的会议 (我们称之为Friends & Family meeting)。当为一个共同的大项目工作时,我曾安排不同的部门成员(工程师、支持、数据分析、金融财务)坐到一起进行项目冲刺。这是拉近相互之间距离的非常有效的一个做法, 尤其对于减少扯皮的机会. 因为互相之间经常会请或被请喝咖啡 (可称之为”咖啡外交”). 我也会经常和一些人约定吃工作午餐, 经常聊的是家常, 增的是感情。有的时候一次长距离的散步也更能让人畅所欲言。而这样的紧密关系,在我们面对一个极具挑战性的项目的关键时刻,会帮助大家紧紧的抱团闯关.

7、习惯委托, 但不要盲目, 请谨慎

分配任务委托别人的重要性比较容易理解. 因为你不是超人, 不能端茶倒水什么都做吃喝拉撒什么都管. 有些时候, 你往往还不是最适合的人选. 当团队一大事情一多, 你一定要学会委托别人来负责合适的任务. 对有些领导者而言, 委托别人一个重要的目标可能不是很放心, 觉都睡不好; 但我非常习惯委托别人, 有时候可能太习惯了. 这是我一位前老板给我指出来的一个问题. 有一次我给一位组员分配了一个既有技术难度又有协调挑战的难题. 进程比较缓慢. 但我给了他太多的时间空间来折腾, 而事实上他在某些方面需要一些加强, 有些方面需要我更多的主动的帮助. 我老板指出来, 如果我要让别人随便折腾的话, 前提是我需要有足够的信心. 我需要有事实来逐渐证明我的决定是正确的. 需要谨慎委托. 因为如果项目失败, 对他而言, 最终负责的人还是我, 不是别人. 所以我不能以别人不行来给失败的委托埋单.

如果你有一个重要的任务需要委托给别人, 你要么

1) 已经对此人非常了解. 知道他战斗力非凡可以搞定; 或者相信他可以迅速学习提高打鸡血搞定;

要么

2) 需要在一开始手把手教他, 时不时问他, 直到你对他有足够的信心.

具体我是这么做的. 项目开始时, 我让被委托人给我一个整体计划以及几天内可以完成的任务. 一开始经常会面跟进, 然后确定后几天的任务. 根据每次完成状况来估计他能不能”高快狠”地完成最终的目标. 信心逐渐建成后可以减少关于该项目的细节讨论. 此时的委托可以放得更开. 但有一点要注意, 如果跟的太紧的话, 可能让人觉得你对他不放心, 他也会做得畏首畏尾, 这可能比盲目的委托还更差. 所以在委托和谨慎之间, 有一个微妙平衡.

我觉得在这一点上我还要加强. 这里也和大家提个醒.

8、意见反馈应该一个持续性的, 而不是一年一次或两次的活动

一年一度或两度的意见反馈在硅谷公司是非常常见的. 它的目的不是设置起来给员工难堪, 让他们互相责难的. 它的目的是希望员工对自己对他人有更全面的认识, 以助进步. 意见反馈有自我反馈和同事反馈两部分. 自我反馈是自己评定自己, 完成了哪些目标, 错失了哪些目标, 哪些方面做好了, 哪些方面还待进步. 但由于是自己踢球兼裁判, 难免有偏颇. 同事反馈, 就像一枚镜子, 让你看到180度之外的自己. 在Facebook, 360度的正式意见反馈是一年两次, 并且和薪酬挂钩. 但近年来, 意见反馈和薪酬评定逐渐分开. 比如我做的一件事就是季度性的意见反馈, 时间和正式评定错开. 在那几天中, 我请求所有相关组的同事在自愿的前提下给我写写关于我直属组员的意见反馈, 短短几句都行. 我会收集, 综合, 最后在1-1碰头会时反馈给我的组员.

如果需要等半年才来收集意见的话, 很多相关故事早以忘得一干二净. 故事越久远, 记忆越模糊, 意见越空洞, 说了等于没说. 而且, 意见反馈和薪酬绑在一起, 正常人(即使是牛人)都会很自然的把心眼更多的放到薪酬上, 而不是意见本身.

除了季度性的轻型意见反馈, 日常的意见反馈如果有的话应当立马传递. 趁热打铁效果更好.

如何有效传递整理好的意见也很重要. 有句话是说”it’s not what you say that matters, it’s how you say it”. 我没那么极端, 我觉得如何传递意见也同样重要. 有两种方式我都试过, 不确定哪种更有效. 这里都谈一谈. 一种是以问为主逐渐深入促其思考, 比如”how did you think about the meeting you hosted yesterday”; 另外一种是赤裸裸的直入主题, “hey, let’s talk about the meeting you held yesterday”, 然后开始谈我自己的感觉. 不管哪种方式, 一定要给对方一个解释自己行为的机会; 永远假设并告诉他我相信他的意愿是好的. 为了避免陷入”你昨天做了xxx” “没有, 我做的是yyy” “我觉你是做了xxx”的死循环式的争论, 我首先争取和他们在”我们感知的即是事实”这一点上达成共识. 基于这点前提, 我们把讨论的重点放在如何做能改变别人的感受最后让事情能顺利完成, 毕竟大多数重要的事都有很多人一同协作完成. 当他们认识到自己想要改进某个方面的时候, 如何改是一个相对容易很多的问题 – 聪明人一向能够找出改进的办法, 我所做的就是配合他们做头脑风暴. 最终谈话的目的是产生一个下次如何能做的更好的具体方案.

关于有效传递意见反馈, 另有4点提一下.

1) 意见反馈不见得都是负面的. 它可以是别人的一个长处. 你很欣赏. 你希望他这方面坚持做, 做得更多. 比如一句”hey, I really love your weekly summary email with the key metrics at the top. Please keep them coming”可能产生很好的激励效果.

2) 意见反馈必须摆事实和讲道理. 如果你只是告诉别人他很烂, 但不说什么时候浪过了以及为什么, 除了给他添点火气之外无他用. 所以我在相关人员包括自己写意见反馈的时候要求提供实例. 比如一句 “I think he could make meetings transparent and shorter by having an agenda, like the weekly data review meeting on last Friday”比”his meeting is too long”更有血有肉有效.

3) 意见反馈必须是可操作的. 让人无从下手的意见意义不大. 如果在提意见的同时提出一个方案以供参考就有意义的多. 但注意, 绝不能是命令的方式 (那是中青宝…). 比如前面的例子”I think he could make meetings transparent and shorter by having an agenda sent ahead of time…”就很容易操作.

4) (个人偏好) 在最近的两个评价周期中, 我给15个左右的同事(一半不直属我)写过意见反馈. 我把我写的直接分享给他们. 出于这种想法, 在我下笔时就少了很多冲动. 因为他们会读, 所以我无法做到背后捅刀. 因为他们要读, 所以我需要写得有意义, 容易理解, 并且加上很多例子. 并且, 我欢迎他们和我直接讨论. 如此一来, 他们也明白我写这些反馈的一片苦心是为了他们进步.

9、你可以比你想象的做得刚好

这不是说说而已. 我自己就有一个亲身的例子. 我们曾经认为把一个高得离谱的欺诈率降到所允许的范围内会很难. 的确很难. 但想想看我们最终牛逼了一把, 把它降到了比允许上限的一半还要低. 感觉很爽. 很长一段时间内整个团队士气高昂信心爆棚做事像开了外挂.

牛人们总是不断的超越自己. 给他们一个离谱的目标, 配以应有的工具, 适当的帮助, 足够的信心还有一定的时间, 他们会让你大吃一惊, 也会让自己大吃一惊. 这一点, 乔帮主是行家, 屡试不爽.

但做到这一点有一个前提 – 不能害怕犯错. 如果犯错是被要严惩的失败是不允许的话, 牛人们只能在框框中被圈养, 没有办法实现突破. 有一句话我经常挂在嘴上”ask for forgiveness, not for permission”. 在Facebook, 大胆行事犯错是容易被原谅的.

但反过来, 有一点要小心, 就像第7点所说的 – 你不能随便把一个离谱的目标交给一个人, 然后期待他来给你惊喜. 盲目带来的可能是惊吓. 你需要真正的牛人, 至少是潜在牛人. 而作为一个领导者, 你的一个任务是帮助他们, 鼓励他们, 来引爆自己的潜力点. Facebook不缺此类待引爆的牛人.

10、不要过多设计或者过早优化

有些工程师有一股出于本能的冲动想把自己的程序规模化, 甚至在这些程序还没看到大规模使用的曙光之前. 我在Facebook开始的时候, 也是冲动型工程师一杯. 但经历过几次失败的产品之后, 我牢记了这个教训. 不要过多设计或者过早优化. 把核心功能设计的简单精炼. 只有在看到产品有被大规模使用的趋势后, 才来增加功能或增加规模量. 有一个我做的产品使用的上限是200万月用户(当时Facebook整个月用户群是4000万左右), 但我的实现已经做了很多额外的功来满足更多的用户. 做的时候感觉很爽(感觉自己很牛, 感觉再多人用产品也不会崩溃), 之后感觉很惨.

但这一点不一定能适用于架构上的工作. 比如Friendster这个网站的失败就是其基础架构的性能长期无法应对急速增长的用户以致网站很慢甚至崩溃. 在用户增长高潮来临之前, 你应该已经在架构上做了足够多的前戏. 否则搞不好就要像Friendster收摊子散伙. 但同时也要意识到, 你所看到的用户访问模式, 你的网站功能, 在你只有10万用户的时候, 可能和你有1亿用户的时候会很不一样. 所有太多太早太频繁的架构上的大动作可能会适得其反. 这一点上, 你要小心判断.

结语:

在Facebook的4年半很好玩. 我学到的感受到的远多于以上的十项. 但希望这个分享能对朋友们有点帮助. 同时祝所有的朋友在自己现在扮演的角色上都有好运。

本文来源:王淮博客