太阳侠

我是一颗恒星


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

梁宁演讲:在产品里修行

发表于 2020-03-25   |   分类于 生活感悟

梁宁演讲:在产品里修行

大家好,我是梁宁,今天我演讲的题目叫做《在产品里修行》。

做一个产品就是你的修行,因为在这个过程里,你需要认识这个世界,你需要认识人的弱点。你需要认识你的本性,并且不去挑战它。你需要认识你的合作伙伴的本性,并且知道怎么去做跨文化的交流。

##你需要洞察人性并且不去挑战它

做产品和做运营是两种人格

我们在讨论这次课程的时候,说到一个现象:为什么现在优秀的产品经理里面女性很少?

一个很重要的原因就是大多数女性是容忍度非常高的人。容忍度高的人,其实是做不了好产品的。她很难把别人逼到角落里还要坚持自己主张。

产品经理最重要的是有创造力。而创造力是自我的延伸,所以创造力强的人都是极端以自我为中心的人,很难照顾别人的感受。

他的自我造就了他对产品的敏感和决不妥协的态度,以及推到一切的创造力。所以我们看到乔布斯其实就是一个绝对自我的人。

腾讯里面关于产品还有另外一个岗位,叫做运营经理。运营经理最重要的是控制,控制节奏,控制资源,控制结果。控制其实是自制力的延伸。

你会发现,作为一个人类,你不可能同时具备超强的自我和超强的自制。所以你如果是一个非常好的营销人员,一定不是一个好产品经理,因为他太爱迎合别人,太懂得体贴别人的人。

##最大的成本就是用错人

作为一个创业的公司,很重要的一件事就是,你需要和优秀的人建立重度关系,你不能把时间都放在不优秀的人身上。

如何去发现优秀的人?他们有三个特点,第一个是敏感度高,第二个特点是容忍度低,第三个特点是主动优化。

1,敏感度高,其实和每个人的天分有关。有的人一眼就看出有问题,而有的人却很难觉察。这个在面试的时候就应该果断判断,因为让一个人做他不擅长的事情,只能带来双方的痛苦和时间浪费。

2,容忍度低,从某种程度上来件,其实是一种文化的塑造。比如我们的父母,他们都是在一个完全集体主义的环境中成长起来的,所以他们的成长环境决定了他们势必要学会妥协、容忍,差不多就行了。中国制造、中国产品的特征,同样也是这种高容忍度的产物。

3,主动优化。一个人发现了问题,他是在不停抱怨还是主动优化?这个取决于你和他的沟通和鼓励。

比如我家很乱,我请了一个阿姨来打扫,但是她第一次来,她肯定得不停地和我沟通,哪些可以扔哪些不能动。但是时间长了以后,你不用多说,她也可以自动优化了。

所以我们在搭建团队的时候,首先就是你必须快速地察觉他是不是有足够的敏感度,其次,用你的沟通和鼓励让他从一个敏感,容忍度低的人变成一个能够主动优化的人,这是我们搭建一个好的创业团队的关键。

##你对世界的洞察在你的产品之中

你对于世界的洞察,对于产业的掌控力,其实都在你自己的产品当中。接下来我们说一说对产品的洞察。

我想分为产品、用户、场景三点来分析。

你要提供的产品,是你能够持续驾驭的产业链的长度、力度和精准度。

产品是你提供服务的能力

先看产品。产品不是简单的APP界面,而是你提供服务的能力。

我之前做过一个旅游网站,后来被腾讯全资收购,于是有了在腾讯学习工作的三年。在腾讯的内部交流里,没有人谈产品和功能,大家谈的是服务和特性。

为什么?因为你在谈产品,有可能一个功能扩展起来就是一个产品,比如说评论,对于很多人来讲是一个功能,但是你把它整个运营好,它就是微博。

所以不谈产品,谈服务,我们关心你提供的到底是一个什么样的服务?

这种思路就解决了不是以产品经理的个人认知为中心,而是以服务对象的需求和满意度为中心去优化产品、设计服务的问题。

真正关键的是产品的隐性特征

我在腾讯学会的第一节产品课是一台ATM机。

第一个问题,ATM机提供什么服务?取现。第二个问题,ATM机有什么特性?

一堆的产品控可能跳出来说:屏幕是什么颜色的?是先出卡还是先出钞?能否支持手机扫码取现?

其实这些都是ATM机的显性特征。那么ATM机的隐性特征是什么?

大家知道在一台ATM机里面会放现金?一台ATM机基本四个钞箱,一个钞箱是20万现金,四个都装满了是80万。但大多数ATM机会放50万现金在里面。为什么?因为这些放在ATM机的现金是不能产生利息的。

也就是说,当ATM提供为柜台分流取现压力的同时,它同时也分流了这个企业的核心资源。

所以如何通过数据统计支持决策,既能为用户提供充足的取现服务,又能避免过多的资金闲置,成为ATM机的隐性特征。

第三个问题,ATM服务的全流程是什么?

表面上来看,用户只需要插卡、输入密码,就可以取现。但是从企业角度来看,它至少需要这些流程去支持一台ATM机的正常运转。

战略部门。它来确定我们为什么需要一台ATM机。

战略价值分两个:分流柜台窗口的取现压力;在人流多的商场设置ATM机,可以向用户传达品牌亲近感和安心感。

运营部。用数据分析支持决策:在哪些网点设置ATM机以及放置多少现金。

运营部四个功能:第一个增撤网点;第二个现金管理,包括现金的回收和放置;此外还需要两个人,一个人管硬件,一个人拿钥匙。

硬件维护。ATM机的无法打印凭条,断电等等问题的处理。

客服。取钱吞卡,出钱有误等等问题处理。

就是说这么一台最简单的产品,它的背后需要至少7个岗位来围绕它工作。

###结论

当我们谈起产品,绝大多数人想到的只是APP的界面,但实际上对产品的定义是完整的服务流程,和总体的服务成本。你要提供的产品,是你能够持续驾驭的产业链的长度、力度和精准度。

什么叫长度?京东的供应链和物流控制能力。

什么叫力度?比如双十一大战时,天猫向供应商要求,你只能向我供货,我是你的唯一分销商。这就是力度。

什么是精准度?我重仓压一个什么东西,结果搞错了,这就是精准度的问题。首先去搞清楚,自己要提供的到底是什么服务?

最后再去想怎么展现,是用APP还是网站还是实体店,这些都只是产品的显性特征和外化模式而已。

不管是小闲还是笨笨,最后都会转化为笨笨,这里面是一个情绪触发的过程。

好的产品从精细的用户画像开始

第二个,用户。

刚刚我们举的一台ATM机的例子,我们说它是最简答的产品。为什么,因为它是唯一一个不用考虑用户细分的产品。

但是除了钱之外的任何一个产品,你都需要做用户细分,去研究用户画像。所以大家记住,我们做的东西是一定是远比一台ATM机复杂的产品。

###三类最简单的用户画像

关于用户画像,我们从最简单的三个用户说起:

第一个用户叫“大明“。大明的特点是什么呢?他决定暑假的某一段确定的时间带小孩去新加坡旅游。他要做什么,什么时间做,他非常清楚。

他对自己所要的东西已经非常清晰了,所以给我硬货,好的配置和好的价格,最快的效率,这就是大明需要的。

中国最早的电子商务网站,都是服务于大明的。这些网站的共同特点就是大大的搜索框,强大的检索功能,非常快地找到自己要的东西,这对大明来说,就是最好的服务。

还有一类叫“笨笨”。笨笨什么特点呢?暑假我想出去玩,但是去哪儿呢?欧洲没去过,巴厘岛也没去过,听说新加坡也挺好的,好多人都去日本…然后我去哪儿玩呢,有可能她最后去了漓江,或者她哪儿也没去,就在北京怀柔延庆溜达了一下。

笨笨的特点就是不知道自己要什么。你给我搜索框,可是我还不知道自己要什么?我需要浏览,我需要逛,可能我花了8个小时逛街,本来要买的裙子没有买,而是买了一把雨伞和几双袜子。

所以互联网崛起的第二类电商其实是服务于笨笨的。蘑菇街,小红书都是这样的模式,给你充分的浏览,在你的浏览过程中,设计促进购物决策的环节。

还有一类叫“小闲”。我没有想去旅游,我就是无聊来网上瞎逛。小闲其实就是你我的常态,就是我们的需求没有被触发之前,其实人人都是小闲。

其实腾讯是一个非常经典的服务小闲的公司,为什么呢?QQ聊天是因为闲,刷微信朋友圈也是因为闲,你在任何一个闲的时候,你只要打开腾讯的产品,都可以足够让你打发时间。

所以从腾讯的小闲延伸出来,到游戏和视频的转化率就非常高,为什么?因为游戏也好、视频也好,它本质上都是沿着小闲的行为路径,让大家继续打发时间的一个行动。

这是三种用户的不同的状态。

不管是“小闲”还是“笨笨”

最后都会变成“大明”

从小闲到笨笨到大明,其实这是一个连续的情绪触发的过程。怎么解释,其实当用户的情绪被触发,锁定了他要做什么事情的时候,小闲和笨笨就变成了大明。

你要服务小闲,你就需要提供一个打发时间的东西,豆瓣、天涯、猫扑、这些社区网站就是这类产品。但是我们看到这类产品向交易导流的效果都不太好,其实就是因为从小闲到大明的转化流程过长。

笨笨的产品就很典型,比如说美丽说,蘑菇街,我先收藏,收藏了很多以后,我到淘宝上去搜同类,搜到最喜欢的款式以后,我再去比价,找到最便宜的那家,然后购买。

上面就是一个比较经典的用户从小闲到笨笨到大明的转化过程,其实我们每个人都会有一个情绪被激发和需求变明确的过程。

但是不管这个用户之前是小闲还是笨笨,是男是女,最后购买的一瞬间一定是变成大明。而搞定大明的唯一的办法就是提供硬货。

场景是通过情绪触发和意见挟裹引导用户决策的过程。

场景是引导用户决策的过程

##第三个是场景。

从小闲到笨笨再到大明这个过程中,其实有非常多的具体和建设场景的工作要做。

场景是什么?“场”是停留时间和消费时间,而“景”是情绪触发和意见挟裹。

如果你只提供了一个广告,但是你没有给用户提供停留空间,然后在这个停留时间里面去激发用户的消费情绪,那么这个广告转化成购买的距离还是非常遥远。

情绪是最支持人做决策的一个动力。下一件事情是互动,那互动的本质其实是你对用户行为的影响。

营销活动就是这么一个场景,让用户停留在我搭建的场景里,花时间了解,酝酿情绪,然后他被周围的意见挟裹,被你引导,这就是营销的核心。它的核心不在于你提供一个功能,而在于你搭建了一个场景。

举个例子,罗辑思维

罗辑思维有一次打包卖书,就是这个套装里面有6本书,但是你不知道你们都有哪些书,而且限量8000套来销售。

一个淘宝店主就觉得这个套装一定有价值,因为限量必须要抢购。所以他在开卖的第一时间就抢购了10套,在紧接着的1个小时内8000套书就售罄了。

罗辑思维的群里还有人在问,怎么没了,还能到哪儿买?于是这位淘宝店主就把他买的10套书上架销售。

他就想说,大家都想买买不到,我怎么着也得加点价吧。于是他加了点价450开卖,放了两天没人来问,降到400,还是没人问,然后打折,还是没有人问。最后这套书在淘宝是零交易。

为什么同样一套书,在罗辑思维上是1小时8000套一抢而空,但是在淘宝店主这里是打了对折,放了10天还是零交易呢?

原因就在于罗辑思维其实搭建了一个场景,对消费者进行意见挟裹。这里面最核心的是什么?如果你架构的场景,不能影响别人的情绪,不能对别人造成情绪触动的,那它就不是一个场景。

手机App扫码登录Web端,技术上是怎么实现的?

发表于 2020-02-15   |   分类于 技术日记

手机App扫码登录Web端,技术上是怎么实现的?

1、引言

扫码登录这个功能,最早应该是微信的PC端开始搞,虽然有点反人类的功能(不扫码也没别的方式登录),但不得不说还是很酷的。

下面这张图,不管是IM开发者还是普通用户,应该很熟悉:

于是,搞IM产品的老板和产品经理们,从此又多了一个要抛给程序员们的需求——“为什么微信有扫一扫登录,而我们的没有?”。

好吧,每次只要是微信有的功能,IM程序员们想甩锅,难度就有点大了,毕竟老板们都都会想当然认为,微信有的“我”的IM产品里也得有。

既然无法回避,那就只能老老实实搞懂技术原理,然后自已使劲撸吧。

本文将简要的介绍扫码登录功能的技术实现逻辑,并实际结合淘宝、微信的扫码登录功能,学习和研究大厂主流应用的技术实现思路。

2、基本技术原理

2.1 扫码登录功能到底是什么样的?

首先介绍下什么是扫码登录。现在大部分同学手机上都装有微信、qq和淘宝这一类的软件。而这些app都有他们相对应的网页端。为了让用户在使用他们的网页时登录更加方便和安全,使用手机扫一扫就可以登录的服务,就显得自然而然了。

几个主流大厂应用扫码登录时的界面效果如下:

有很多小伙伴可能会感到很神奇,网页上只是显示了个二维码,它怎么就知道是哪个手机扫到了二维码,并且进行登录的呢?而且,登录完成以后,还能直接把用户信息显示给用户,真的是很神奇啊。

2.2 扫码登录功能的完整技术逻辑

1)网页端与服务器的配合逻辑:

接下来就是对于这个服务的详细实现。

首先用户打开网站的登录页面的时候,向浏览器的服务器发送获取登录二维码的请求。服务器收到请求后,随机生成一个uuid,将这个id作为key值存入redis服务器,同时设置一个过期时间,再过期后,用户登录二维码需要进行刷新重新获取。

同时,将这个key值和本公司的验证字符串合在一起,通过二维码生成接口,生成一个二维码的图片(二维码生成,网上有很多现成的接口和源码,这里不再介绍)。然后,将二维码图片和uuid一起返回给用户浏览器。

浏览器拿到二维码和uuid后,会每隔一秒向浏览器发送一次,登录是否成功的请求。请求中携带有uuid作为当前页面的标识符。这里有的同学就会奇怪了,服务器只存了个uuid在redis中作为key值,怎么会有用户的id信息呢?

这里确实会有用户的id信息,这个id信息是由手机服务器存入redis中的。具体请继续阅读“手机端与服务器的配合逻辑”。

2)手机端与服务器的配合逻辑:

话说,浏览器拿到二维码后,将二维码展示到网页上,并给用户一个提示:请掏出您的手机,打开扫一扫进行登录。

用户拿出手机扫描二维码,就可以得到一个验证信息和一个uuid(扫描二维码获取字符串的功能在网上同样有很多demo,这里就不详细介绍了)。

由于手机端已经进行过了登录,在访问手机端的服务器的时候,参数中都会携带一个用户的token,手机端服务器可以从中解析到用户的userId(这里从token中取值而不是手机端直接传userid是为了安全,直接传userid可能会被截获和修改,token是加密的,被修改的风险会小很多)。手机端将解析到的数据和用户token一起作为参数,向服务器发送验证登录请求(这里的服务器是手机服务器,手机端的服务器跟网页端服务器不是同一台服务器)。

服务器收到请求后,首先对比参数中的验证信息,确定是否为用户登录请求接口。如果是,返回一个确认信息给手机端。

手机端收到返回后,将登录确认框显示给用户(防止用户误操作,同时使登录更加人性化)。用户确认是进行的登录操作后,手机再次发送请求。服务器拿到uuId和userId后,将用户的userid作为value值存入redis中以uuid作为key的键值对中。

3)登录成功时的逻辑:

然后,浏览器再次发送请求的时候,浏览器端的服务器就可以得到一个用户Id,并调用登录的方法,生成一个浏览器端的token,再浏览器再次发送请求的时候,将用户信息返回给浏览器,登录成功。这里存储用户id而不是直接存储用户信息是因为,手机端的用户信息,不一定是和浏览器端的用户信息完全一致。

4)详细的技术原理总结如下图所示:

3、淘宝的扫码登录技术实现

本节我们以淘宝的扫码登录为例,来实际研究分析一下淘宝的扫码登录实现逻辑。

登录界面 https://login.taobao.com/member/login.jhtml 传回来的参数为:

然后请求(GET)报文是这样的:

https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do?
lgToken=2c3b4d53ef0513787bf4ce711ea5ba53&defaulturl=&_ksTS=1540106757739_2804&callback=jsonp2805

关键的就是lgToken,是网页的唯一ID,当打开了二维码登录的时候,网页在轮询(应该是长轮询long polling)调用接口去请求服务器。扩展:彻底理解cookie,session,token

如果没有扫码,返回的为:

如果扫了的话则会返回:

{

    "code": "10001",

    "message": "mobile scan QRCode success",

    "success": true

}

长时间没有扫码的话,网页端会停止轮询,二维码失效!

当手机端确认登录后,接口返回的是:

{ 
"code": "10006", 
"success": true,
 "url": "https://login.taobao.com/member/loginByIm.do?uid=cntaobaoxxx&token=ff82fc0d1d395a33d3b38ec5a4981336&time=1530179143250&asker=qrcodelogin&ask_version=1.0.0&defaulturl=https://www.taobao.com&webpas=0b7aed2d43f01825183e4a49c6cae47d1479929926"
}

表示登录成功,当然手机端与服务端在点击”确认登录”之间的交互可能就是这样:网页端生成的lgToken去请求服务端,服务端记住了这个lgToken并认为登录了,当网页端再次轮询请求接口时,就返回真正的登录态Token,网页端此时就可以凭着这个Token来登录了。

详细的技术逻辑如下图所示:

4、微信的扫码登录技术实现

4.1 技术原理流程图

微信的网页版访问地址是:https://wx.qq.com/,有兴趣也可以自行深入研究。

4.2 实际的技术实现逻辑

1)获取唯一的uuid, 以及包含uid信息的二维码:

// 获取uuid

getUUID: function() {

    vare = t.defer();

    returnwindow.QRLogin = {},

    $.ajax({

        url: i.API_jsLogin,

        dataType: "script"

    }).done(function() {

        200 == window.QRLogin.code ? e.resolve(window.QRLogin.uuid) : e.reject(window.QRLogin.code)

    }).fail(function() {

        e.reject()

    }),

    e.promise

}

2)浏览器轮询服务器,获取扫码状态:

// 查看扫码状态

checkLogin: function(e, a) {

    varn = t.defer()

        , a = a || 0;

    returnwindow.code = 0,

    window.checkLoginPromise = $.ajax({

        url: i.API_login + "?loginicon=true&uuid="+ e + "&tip="+ a + "&r="+ ~newDate,

        dataType: "script",

        timeout: 35e3

    }).done(function() {

        newRegExp("/"+ location.host + "/");

        if(window.redirect_uri && window.redirect_uri.indexOf("/"+ location.host + "/") < 0)

            returnvoid (location.href = window.redirect_uri);

        vare = {

            code: window.code,

            redirect_uri: window.redirect_uri,

            userAvatar: window.userAvatar

        };

        n.resolve(e)

    }).fail(function() {

        n.reject()

    }),

    n.promise

}

3)根据服务器返回的扫码状态,进行相应的操作:

408 扫码超时:如果手机没有扫码或没有授权登录,服务器会阻塞约25s,然后返回状态码 408 -> 前端继续轮询

400 二维码失效:大约5分钟的时间内不扫码,二维码失效

201 已扫码:如果手机已经扫码,服务器立即返回状态码和用户的基本信息 (window.code=201,window.code.userAvator=”…”),-> 前端继续轮询

200 已授权:如果手机点击了确认登录,服务器返回200及token -> 前端停止轮询, 获取到token,重定向到目标页

具体的代码示例如下:

// 根据服务器返回的扫码状态,进行相应的操作

functiono(c) {
    switch(c.code) {
    case200:
        t.newLoginPage(c.redirect_uri).then(function(t) {
            varo = t.match(/<ret>(.*)<\/ret>/)
                , r = t.match(/<script>(.*)<\/script>/)
                , c = t.match(/<skey>(.*)<\/skey>/)
                , s = t.match(/<wxsid>(.*)<\/wxsid>/)
                , l = t.match(/<wxuin>(.*)<\/wxuin>/)
                , d = t.match(/<pass_ticket>(.*)<\/pass_ticket>/)
                , f = t.match(/<message>(.*)<\/message>/)
                , u = t.match(/<redirecturl>(.*)<\/redirecturl>/);
            returnu ? void (window.location.href = u[1]) : o && "0"!= o[1] ? (alert(f && f[1] || "登录失败"),
            i.report(i.AUTH_FAIL_COUNT, 1),
            void location.reload()) : (e.$emit("newLoginPage", {
                Ret: o && o[1],
                SKey: c && c[1],
                Sid: s && s[1],
                Uin: l && l[1],
                Passticket: d && d[1],
                Code: r
            }),

            void (a.getCookie("webwx_data_ticket") || n.report(n.ReportType.cookieError, {
                text: "webwx_data_ticket 票据丢失",
                cookie: document.cookie
            })))
        });
        break;

    case201:
        e.isScan = !0,
        n.report(n.ReportType.timing, {
            timing: {
                scan: Date.now()
            }
        }),
        t.checkLogin(e.uuid).then(o, function(t) {
            !t && window.checkLoginPromise && (e.isBrokenNetwork = !0)
        });
        break;

    case408:
        t.checkLogin(e.uuid).then(o, function(t) {
            !t && window.checkLoginPromise && (e.isBrokenNetwork = !0)
        });
        break;

    case400:

    case500:

    case0:
        vars = a.getCookie("refreshTimes") || 0;
        s < 5 ? (s++,
        a.setCookie("refreshTimes", s, .5),
        document.location.reload()) : e.isNeedRefresh = !0;
        break;

    case202:
        e.isScan = !1,
        e.isAssociationLogin = !1,
        a.setCookie("login_frequency", 0, 2),
        window.checkLoginPromise && (window.checkLoginPromise.abort(),
        window.checkLoginPromise = null),
        r()
    }

    e.code = c.code,
    e.userAvatar = c.userAvatar,
    a.log("get code", c.code)

}

4.3 小结

微信网页端扫码登录时,轮询的数据返回采用的是JSONP的形式,这是为了解决跨域问题。如对JSONP不了解的,可以参考:

http://www.52im.net/thread-1038-1-1.html

微信网页端扫码登录时,轮询采用了后台根据扫码情况阻塞前台请求,优化轮询及减少前端的无效轮询。这种技术,请详见:

http://www.52im.net/thread-338-1-1.html

5、本文小结

扫码登录这个功能,现在已经不只出现有IM应用里,各种带有移动端的线上网站也都有了这个功能,所以本文中介绍的技术原理并不局限于只用于实现IM应用中的扫码登录。

另外,为了方便抓取真实的数据进行分析研究,本文中的PC端案例分析是针对的是网页端,但实际上如果你的PC端是富客户端(也就是.exe、.dmg这样的安装版),原理也是一样的,而且还不需要考虑浏览器里的跨域问题等。

阅读本文时,可能涉及到传统的Web端即时通讯技术(为了扫码登录的实时性),比如长轮询等,如果您对这些技术还不太了解的话,可以系统学习一下即时通讯网整理的有关Web端即时通讯方面的资料。


本文参考链接1:来源微信公众号

本文参考链接2:即时通讯网

PHP5.6通过CURL上传图片@符无效的兼容问题

发表于 2020-01-10   |   分类于 技术日记

今天本来想试试一个图片云的API,于是本地做了个上传图片的测试,结果灰常郁闷的发现以前一直用的好好的CURL上传图片居然死活不起作用,本来几分钟搞定的事情,结果折腾了大半天才终于找到原因,居然是兼容性问题,真是无语。。

网上搜索PHP通过CURL上传图片几乎都是类似下面的代码:

<?php
header('Content-type:text/html; charset=utf-8'); //声明编码
$ch = curl_init();
$url = 'https://xxx.com/api/mobile/auto_upload.php?uid=9705459';

//post数据,使用@符号,curl就会认为是有文件上传
$curlPost = array('Filedata'=>'@/Users/finup/Documents/11.png');


curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1); //POST提交
curl_setopt($ch, CURLOPT_POSTFIELDS,$curlPost);
$data =curl_exec($ch);
curl_close($ch);
echo '<pre>';
var_dump($data);

以前上传图片都是在图片路径前面增加一个 @符号,如:

$file = __DIR__ .'/0634134726bc5b8b.jpg';
$data = array('mypic'=>'@'. $file);

这样就行了,但现在这种情况一般只适用于 PHP5.6以下的版本。
对5.6来说,直接加@是木有用的啦。

解决办法有两个:一种是兼容;二是使用新的方法。

1 . 兼容方法:
主要用到 CURL 的一个配置参数 CURLOPT_SAFE_UPLOAD
CURLOPT_SAFE_UPLOAD 在 PHP5.5中默认值是 false
而在 PHP5.6中已经默认为 true 了。
所以只需要增加一行强制设置为 false 就行,如下:

注意:该参数的设置顺序,必须在设置 CURLOPT_POSTFIELDS 参数之前才有效哦!!!

<?php
$url = 'http://127.0.0.1/test3.php';
$file = __DIR__ .'/0634134726bc5b8b.jpg';
$data = array('mypic'=>'@'. $file);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$content = curl_exec($curl);
curl_close($curl);
print_r($content);

2 . 新的图片上传方法:
使用 CURLFile 类来处理文件,如下:

$url = 'http://127.0.0.1/test3.php';
$file = __DIR__ .'/0634134726bc5b8b.jpg';
$data = array('mypic'=>new CURLFile($file));
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
$content = curl_exec($curl);
curl_close($curl);
print_r($content);

我这里只是最简单的应用,具体可参考下面官方文档:
http://php.net/manual/en/class.curlfile.php

这下终于上传成功了。。。太坑爹了,一天时间又被折腾完了。

最后,注意使用CURLFile类时的一个问题:

CURLFile的第三个参数,如果使用的话,要么带上后缀的文件全名;要么整个空着。不能有值又不带后缀,否则DZ系统默认上传失败,因为获取文件扩展名为空。

当然,如果像上面示例一样只有一个文件路径本身,其他全都是缺省值(默认值),服务器会自动获取其他文件属相参数,反而是一个更好的方案。

iOS 支持通用链接UniversalLinks

发表于 2019-12-28   |   分类于 服务器

iOS 支持通用链接UniversalLinks

关于iOS中的Universal Links(通用链接)分三部分讲解一下。
这个功能是从 iOS 9 之后开始支持的。


第一部分:一篇文章《iOS微信里打开app,Universal Links》

从第三方应用或者浏览器打开自己app的东西

传统的方式是通过URL Scheme的方式,但是iOS9以后又出了新的更完美的方式Universal Links。

传统的URL Scheme方式微信内置的浏览器都是封锁了所有它投资的公司之外的,只有白名单的才可以(比如京东,B站,等)。Universal Links也不能算是完美的实现,但是已经是目前为止最好的了。

就说一下这个东西的介绍,就像在windows里面为某一类型的文件添加了默认的打开方式。只不过这个文件类型变成了某一个“域名”(并非完全是某个域名,或者可以称之为某段有特殊意义的URL)的URL。这个东西只能在iOS9以后才有。

具体的表现在在iOS系统中,当你邮件或者短信或者其他方式收到含有某段“特定标示”的URL的时候如果安装有你的app,就可以直接默认调用app去打开,否则只能调用你的Safari去打开。具体到微信里面就是打开了分享的H5,右上角更多-在Safari中打开,可以直接调用你的app去打开这个URL。具体在app的中怎么展示相关的逻辑就看你的了。

具体介绍的相关文章:

苹果文档:
https://developer.apple.com/library/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html

苹果检测链接有效性:
https://search.developer.apple.com/appsearch-validation-tool/

很棒的一个英文的步骤文章:
https://blog.branch.io/how-to-setup-universal-links-to-deep-link-on-apple-ios-9

相关的文章:http://www.jackivers.me/blog/2015/9/17/list-of-universal-link-ios-9-apps

http://tech.glowing.com/cn/deferred-deep-linking-and-branch-sdk-in-ios/(URL Scheme和Universal Links优缺点介绍的很棒,这个团队的技术博客也很不错哦)

http://www.cocoachina.com/ios/20150911/13321.html(里面的那个运行流程的总结图很不错)

具体的步骤就不再赘述了,因为无论是官方文档,还是其他人写的文章都很棒了,我就说一下实际开发中可能遇到的的坑。

1.注意拼写那个json文件的时候,应该是你的开发者中心,Identifiers—App IDs— 应用的证书名字(bundle id所有对应的那个)—Prefix
.英文的点号,再跟上你的bundle id。并且文件的名字必须为“apple-app-site-association”,不能自己私自定义。用浏览器打开https:///apple-app-site-association文件,看一下成功否就可以了。

2.生成后的json文件一定是要放到你的那些网页所在的站点的目录下面的HTTPS web server根目录下面。比如你的网站是https://www.google.com(所有的网页都是以这个开头的),然后你应用的地址baseurl是https://api.google.com,其实你应该放在www的那个HTTPS web server根目录下面。然后过两三分钟吧,就用苹果有效性检测工具的那个去试一下,找一个你要分享出去的h5链接试一下,只要不出错,出来很多的相关信息就可以了(就跟用这个URL测试出来的结果一样就可以了https://www.yelp.com/biz/michael-winnetka)。

3.在工程的设置Associated Domains的时候,一定先要去苹果的开发者中心打开你的应用证书Associated Domains Enabled。然后记得更新你的证书关联的东西,然后更新本地的证书。才可以打开工程的Associated Domains。记住填写链接的时候是applinks:。这个就是第1点中调试通的那个(如果你的应用的api的和页面的不区分服务器就一样了)。

4.然后编译你的应用。如果你在短信中含有类似的https://?a=1&b=2 已经通过了后,直接长按会出来“在“XXX”中打开”就说明成功了。可以去微信微博等其他的地方去看看了。

这一段内容来源链接(版权归属原作者):https://www.cnblogs.com/ysk-china/p/5777299.html


第二部分:一篇文章《iOS 9 通用链接(Universal Links)》

1.apple-app-site-association文件不能带后缀,务必把”.json”的后缀去掉!有些人的电脑是隐藏文件后缀的,这要格外注意;

2.apple-app-site-association一定要传到域名根目录下;

3.WebServer需要支持https,且https使用有效的证书(是私密链接)。笔者在这里卡了很久,原因就是后台给配的https使用无效的证书,导致应用安装的时候不能正确的下载apple-app-site-association文件;

4.如果想测试这个功能,可以让后台搭一个测试服务器,并配置虚拟主机生成域名,然后iOS这边通过host访问域名就可以了。注意”applink:”后面写的一定是域名,不能是IP;

5.抓包的结果显示,网络顺畅的情况下,应用会在在刚安装(不是打开)的时候会去applink中的地址下载apple-app-site-association文件,所以如果需要测试,请保证网络通畅;

6.当所有都准备好,需要测试该功能的时候,只需要在记事本或短信中输入App能识别的链接,然后直接点击或是长按就可以了,直接点的效果是跳转到你的App,然后右上角是“去网页”的箭头,长按的效果是弹出的菜单中第二项是“在’XXX’中打开”,这也代表着成功。直接在Safari中输入链接是无效的,必须从一处跳入才可以(比如上一级网页)。

7.苹果有个网址(这里)可以检测你的apple-app-site-association是否是有效的,准备好了可以测试一下。

8.测试的时候,建议使用dev证书打包,之后安装到手机上测试功能。未安装应用的情况下直接在手机上跑好像也是可以的,因为抓到过请求。

9.如果你有问题,但上面没有列出,Stackoverflow上面有个问题,可以看下其他人的建议。

继续之前的补充几点

1.如果需要支持此功能,需要在开发者中心做配置。具体是这样:开发者中心->Identitiers->App IDs->需要支持的应用App ID,在Application Services列表里有Associated Domains一条,把它变为Enabled就可以了。

2.当你在项目targets->Capabilities->Associated Domains中配置app link之后,系统会自动帮你写入.entitlements文件,所以不需要自己去手动加。需要注意的是,有人遇到过.entitlements文件没有被加入工程的,这也会产生问题,需要手动把.entitlements加入工程。

3.apple-app-site-association文件里有个paths字段,这个是用来控制可识别链接的,星号的写法代表了可识别域名下所有链接。这篇博客里有很多其他公司的例子,可以参考一下。

这一段内容来源链接(版权归属原作者):https://www.jianshu.com/p/c2ca5b5f391f


第三部分 关于apple-app-site-association文件自己遇到的坑

Configure your website to host the apple-app-site-association file

  1. Buy a domain name or pick from your existing.
  2. Acquire SSL certification for the domain name.
  3. Create structured apple-app-site-association JSON file.
  4. Sign the JSON file with the SSL certification.
  5. Configure the file server.

上面是一篇英文文章说明这个文件的配置过程,很准确。

但是,实际配置过程总遇到的问题有以下几点:

1、此文件在浏览器中访问时,默认是下载而不是打开显示文件内容。

解决方法:在服务器对应项目的配置文件中增加

location ~ apple-app-site-association$ {
    add_header  Content-Type 'text/plain';
}

2、上述方法解决了浏览器直接显示文件内容的问题,但是并不是返回的json格式数据,但是使用苹果的URL检测工具不通过,显示469错误。

解决方法:在服务器对应项目的配置文件中增加

location ~ apple-app-site-association$ {
    default_type application/json;
}

3、上述方法同时解决了显示文件内容和返回json格式的问题,也按上面的方案修改了,但是使用苹果的URL检测工具仍然不通过。

解决方法:注意苹果官网检测工具的一句话“Applebot will crawl your webpage”,需要服务器允许苹果爬的访问权限(默认是禁止所有爬虫的)。在修改允许苹果爬虫Applebot之后,经检测工具检测,apple-app-site-association文件已有效可用。

另外2个问题说明:

1、配置过程中需要多次重启nginx服务器,并且清除浏览器缓存。

2、apple-app-site-association文件的内容是由iOS开发工程师配置好的,此处只涉及服务器上传此文件,并支持检测工具检测到可用状态。

你所不知道的 AI 进展

发表于 2019-10-29   |   分类于 未来探索

人工智能现在是常见词汇,大多数人可能觉得,它是学术话题,跟普通人关系不大。
但是实际上,AI 突飞猛进,正在脱离实验室,进入日常生活。仅仅是现在的技术水平,就足以模糊现实与虚拟的界限,颠覆一般民众的认知。

(图1:2018年10月,世界第一幅 AI 生成的肖像画,拍卖成交价43.25万美元。)

为了让普通人了解 AI 的进展,谷歌的机器学习专家格里高利·萨普诺夫(Grigory Sapunov)写了一篇通俗的科普文章,介绍目前的技术成果。这盘文章非常精彩,有大量的图片,加上一些简单的解释,信息量很大,对于了解技术动态很有帮助。

(图2:谷歌的机器学习专家格里高利·萨普诺夫)
下面就是那篇文章的翻译,比较长,图片很多,但是值得耐心读完。我保证,有些内容一定会让你感到吃惊。

一、图像处理

人工智能最早是从图像处理开始的。图像处理是一种常见任务,智能要求比较高,需要使用 PhotoShop 之类的软件人工编辑,一般的算法解决不了。

1.1 对象补全

2017年,日本科学家提出了一种图像的对象补全模型。经过训练,模型可以补全图片上缺失的部分。

(图3:图像的对象补全模型)
上图中,左边是原始图片,然后把中间的花盆涂掉,输入模型。模型会自动补全缺失的部分(右图),由于它不知道,那里有一个花盆,所以只会根据没有涂掉的部分,补上地板和扶手。
下面是更多这样的例子。涂掉的部分,模型都会补上,哪怕它根本不知道,那里原来是什么。

(图4:图像的对象补全示例)
Nvidia 公司将这个模型做成了产品,放在网上。你可以到它的网站,上传一张图片,然后涂掉一些部分,让网站替你补全。

(图5:涂掉沙发旁边的茶几)
有的图像软件已经应用这项技术,去除人像脸上的斑点。

1.2 背景处理

背景处理指的是,将前景物体从图片分离出来,再对背景进行加工。目前,已经有很好的智能算法可以去除图片背景。


(图6:图片的背景去除)
在模型内部,图片会转成像素的色块。下图的浅紫色块就是前景物体,然后再把这些像素提取出来。


(图7:背景去除模型)
这个模型也已经做成了线上服务,大家可以上传图片感受一下它的效果。
既然可以去除背景,那当然就可以更改背景,为图片合成打开方便之门。


(图8:更改图片背景)

1.3 样式转换

人工智能还能够识别图片的风格样式(即像素的变化规律),将其套用在另一张图片。


(图9:原始图片)
上图是两张原始图片,第一张是梵高的名画《星夜》,第二张是普通的风景照。模型可以提取第一张图片的风格,将其套用在第二张图片。


(图10:套用梵高的《星夜》风格)
其他名画的风格,同样可以套用。



(图11:图像的风格转换)

1.4 图像着色

一旦识别出图片中的物体,模型就可以统计不同物体的像素颜色规律,然后就能推断黑白照片可能的颜色,从而实现照片着色。


(图12:黑白照片的着色)
网上也有免费的着色服务,大家可以体验。

二、GAN 方法

2.1 简介

GAN 是”生成对抗网络”(Generative Adversarial Networks)的缩写,它是一种革命性的提升人工智能模型效果、生成虚拟图像的方法。
原理很简单,就是两个神经网络互相对抗。一个神经网络负责生成虚拟图像,另一个神经网络负责鉴定假图像。理论上,如果 GAN 训练成功,那么生成的假图像与真图像将无法区分。2014年,这种方法提出以后,快速发展,目前效果已经可以乱真。


(图13:GAN 的改进速度)
上图是过去几年,GAN 生成的虚拟人像。可以发现,每过一年,图片越来越大,细节越来越丰富,越发接近真实人像。它的工作方法也是如此,第一步生成一张低分辨率图片,然后慢慢放大,依次修改每一个像素,确定该像素怎样才能最大概率通过鉴定器。
GAN 不仅能生成虚拟图像,还能生成音频、文本,甚至是化合物分子。AI 模型可能创造出来的任何东西,都能使用 GAN 提升效果。GitHub 有一个仓库,专门收集不同用途的 GAN,目前已经有500多种模型。

2.2 StyleGAN

目前,生成虚拟人像效果最好的模型是 Nvidia 公司的 StyleGAN。下面两张头像,你能分辨哪张是虚拟的,哪张是真实的吗?


(图14:GAN 虚拟人像)
这是网站截图,你可以去那个网站试试看,能猜对多少张。需要提醒的是,这是2018年底的模型产物,随着模型进化,迟早将无法分辨真假。
GAN 不仅能生成人像,实际上可以生成任何图像。下面是 BigGAN 模型生成的各种图像,图片里的东西都是不存在的。


(图15:BigGAN 模型生成的虚拟图像)

2.3 图像翻译

一种图像通过 GAN 转变为另一种图像,称为图像翻译。空拍照片变成地图、黑白照片变成彩色照片,都是图像翻译的例子。
pix2pix 是图像翻译的开源工具,它可以让黑夜变成白天,示意图变成实物图。


(图16:图像翻译)
也可以让春天变成夏天,晴天变成雨天。


(图17:图像翻译)
图像翻译的难点在于,它需要有成对的示例(源图像和相应的目标图像),告诉模型应该怎么翻译,这些示例可能很难创建。但是反过来,只要有配对的示例,就可以翻译图像,不管这种翻译是否合理。下面是两只小猫翻译成对应的豹子、狮子和老虎。


(图18:图像翻译)
CycleGAN 模型还支持跨域翻译,将照片翻译成油画,斑马翻译成马。


(图19:图像翻译)
Nvidia 开发了一个 GauGAN 软件,可以在线试玩。用户只需手绘一个示意图,软件就能生成一张对应的风景照片。


(图20:GauGAN 将示意图变成照片)

2.4 人像翻译

图像翻译用于人像,就是人像翻译。StarGAN 模型可以翻译面部属性,比如头发的颜色、性别、肤色等。


(图21:脸部属性的改变)
还可以把其他人的表情移植到你的脸上,下图分别是愤怒、快乐、恐惧的表情翻译。


(图22:表情的改变)
SC-FEGAN 是人像翻译的开源软件,可以让你编辑人像,比如加上刘海,去除墨镜等等。



(图23:人像编辑软件 SC_FEGAN)

2.5 文本到图像生成

GAN 最惊人的成果之一,大概就是根据文本生成图像。用户提供一个句子,软件生成对应的图像。原始文本”一只红中透白、长着非常短的尖嘴的鸟”,可以得到下面的图像。


(图24:根据文本生成图像)
论文甚至提到,将来存在可能,根据剧本直接生成一部电影。

三、视频生成

图像处理逐渐成熟以后,人工智能业界的关注重点就转向了视频。
从一个视频生成另一个视频,这就叫视频翻译。目前比较成熟的两个方向是运动传递和面部交换。

3.1 运动传递

运动传递指的是,将一个人的动作(包括身体、眼睛或嘴唇的动作)翻译到另一个人身上,使得另一个人出现一模一样的动作。
2018的论文《Everybody Dance Now》,给出了一个模型,可以将舞者的动作移植到任何人身上。


(图25:动作传递)
上图中,蓝衣女子的跳舞视频完全是假的,是将左上角舞者的动作套用在她身上,自动生成的。
NVIDIA 公司的开源软件 vid2vid 更为强大,可以生成高分辨率的、连贯的逼真视频。


(图26:vidvid 软件)

3.2 脸部生成

脸部生成指的是,根据一张脸的表情和动作,重建另一张脸。最著名的例子是虚拟的奥巴马演讲。2017年,华盛顿大学的团队发表了一段奥巴马的演讲视频。奥巴马其实从未做过这个演讲,是将别人的表情和口型套在他脸上生成的,语音也是合成的。


(图27:虚拟的奥巴马演讲)
这种伪造的视频被称为 Deepfake(深度伪造),具有很大的欺骗性,许多在线平台都禁止上传这一类视频。


(图28:伪造的特朗普演讲,将喜剧演员的表演变成特朗普自己在讲。)


(图29:深度伪造的普京)
2018年出现的《深度视频肖像》更进了一步,生成的视频不局限于虚拟的面部表情,还会头部旋转、眼睛凝视和眨眼,是 3D 的肖像重构。


(图29:深度视频肖像)
这些技术还在继续发展,现在你可以给出任意文本,从任何你指定的对象嘴里说出来。甚至只凭一张照片,就可以生成一段表情变化的视频。


(图30:一张照片生成各种表情)

3.3 中国的实践

国内的人工智能视频生成,并不落后于国外。换脸应用 ZAO 只需用户上传一张照片,就能把影视剧主人公的脸换掉,好像你本人在表演电影一样。


(图31:换脸应用 ZAO)
2018年,新华社与搜狗合作推出了虚拟新闻主播,具有真人的形象,带有声音、面部表情和动作,在电视上播报新闻,已经开通了英语、俄语、阿拉伯语的主持人。


(图32:虚拟新闻主播)

3.4 视频渲染

除了视频生成,人工智能在视频渲染上也取得了很大进展。
Nvidia 公司2018年展示了实时光线追踪 RTX 技术。这项技术用人工智能预测光线的变化,从而不用耗费大量计算去追踪光线,因此可以实时渲染出高画质的 3D 动画。这对于视频游戏有重大意义。
下面是使用这项技术的 Unreal Engine 4,实时渲染出的一个女子的3D 动画,可以一边计算生成,一边播放,完全没有延迟。



(图32:实时渲染的动画)
实时光线追踪技术还可以用于自动驾驶,在白天和黑夜的不同时间,不同的路面和环境下,预测出暴雨、风雪和强烈的眩光导致的光线变化,对驾驶做出调整。

四、文本和声音处理

最后,简单提一下,人工智能在文本和声音处理领域的进展。

(1)语音合成

谷歌在2018年推出了智能助手 Google Duplex,它会根据你的日程,自动打电话去餐厅订座位。谷歌 CEO 说,这个机器人的对话能力,使得对方完全没有发现这是机器人。

(2)音乐合成

OpenAI 基金会推出的 MuseNet,通过学习数十万段 MIDI 音乐,能做到使用10种乐器,生成一段4分钟的音乐。它的官网有这些音乐的下载,相当动听。

(3)自动评论

据报道,使用 Yelp 网站的数据进行训练的模型,可以自动生成餐厅评论。

- 我喜欢这个地方,一直来这里已经好多年。它是与朋友和家人相聚的好地点,我喜欢这里的食物和服务,从未有过糟糕的经历。
- 我吃了烤蔬菜汉堡配薯条!哦,很好吃!
- 我和我的家人都是这个地方的忠实粉丝。工作人员超级好,食物也很棒。鸡肉很好,大蒜酱也很完美。配水果的冰淇淋也很美味。强烈推荐!
- 上面这些都是机器生成的评论。

(4)智能邮件

Gmail 会根据电子邮件的来信内容,自动生成三种不同的回复,让用户选择。如果只是简单回应,用户不用自己动手写。
Gmail 的另一个功能是,根据用户已经写的内容,预测接下来会写的句子,供用户选择。

五、小结

毫无疑问,人工智能是很酷的技术,创造出了神奇的产品,有着难以想象的巨大应用前景。
但是,人工智能也是一把双刃剑,模糊了现实与虚拟之间的界限,把我们带上了一条不可预测的道路。作为个人,了解这些技术的进展和潜力,有助于保持一份清醒,享受技术之福的同时,避免它带来的一些副作用。
(正文完)


References

[1] 拍卖: https://www.christies.com/features/A-collaboration-between-two-artists-one-human-one-a-machine-9332-1.aspx
[2] 科普文章: https://blog.inten.to/welcome-to-the-simulation-dd0d8cb6534d
[3] 腾讯课堂: https://ke.qq.com/?utm=ruanyifeng
[4] “腾讯课堂101计划”: https://edu.qq.com/a/20190119/005414.htm
[5] 图像的对象补全模型: https://web.archive.org/web/20191016060740/http://iizuka.cs.tsukuba.ac.jp/projects/completion/en/
[6] 它的网站: https://www.nvidia.com/research/inpainting/
[7] 图像软件: https://www.slashgear.com/adobes-entry-level-photoshop-elements-gets-new-ai-powered-tools-04594215/
[8] 很好的智能算法: https://towardsdatascience.com/background-removal-with-deep-learning-c4f2104b3157
[9] 线上服务: https://www.remove.bg/
[10] 更改背景: https://arxiv.org/abs/1703.03872
[11] 识别: https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Gatys_Image_Style_Transfer_CVPR_2016_paper.pdf
[12] 照片着色: https://arxiv.org/abs/1603.06668
[13] 着色服务: https://colorize.cc/
[14] 仓库: https://github.com/hindupuravinash/the-gan-zoo
[15] StyleGAN: https://arxiv.org/abs/1812.04948
[16] 那个网站: http://www.whichfaceisreal.com/
[17] BigGAN: https://arxiv.org/abs/1809.11096
[18] pix2pix: https://github.com/phillipi/pix2pix
[19] CycleGAN: https://github.com/junyanz/CycleGAN
[20] GauGAN: http://nvidia-research-mingyuliu.com/gaugan
[21] StarGAN: https://github.com/yunjey/StarGAN
[22] SC-FEGAN: https://github.com/run-youngjoo/SC-FEGAN
[23] 根据文本生成图像: https://arxiv.org/abs/1711.10485
[24] 《Everybody Dance Now》: https://carolineec.github.io/everybody_dance_now/
[25] vid2vid: https://github.com/NVIDIA/vid2vid
[26] 奥巴马演讲: http://grail.cs.washington.edu/projects/AudioToObama/
[27] Deepfake: https://en.wikipedia.org/wiki/Deepfake
[28] 《深度视频肖像》: https://web.stanford.edu/~zollhoef/papers/SG2018_DeepVideo/page.html
[29] 继续发展: https://www.theverge.com/2019/6/10/18659432/deepfake-ai-fakes-tech-edit-video-by-typing-new-words
[30] 3D 动画: https://venturebeat.com/2018/03/21/epic-games-shows-off-amazing-real-time-digital-human-with-siren-demo/
[31] MuseNet: https://openai.com/blog/musenet/
[32] 自动生成: https://www.theverge.com/2017/8/31/16232180/ai-fake-reviews-yelp-amazon
[33] 三种不同的回复: https://www.blog.google/products/gmail/save-time-with-smart-reply-in-gmail/
[34] 另一个功能: https://ai.googleblog.com/2018/05/smart-compose-using-neural-networks-to.html


严重声明:本文转载自阮一峰的博客,版权属于原作者所有。
原文链接。

下载海外地区的AppStore中应用的方法

发表于 2019-10-11   |   分类于 网络工具

下载海外地区的AppStore中应用的方法

1、官方应用直接下载

如果是下载指定地区的AppStore中的应用,必须拥有此地区的AppID,然后使用此AppID登录AppStore即可随意下载免费应用。

如果需要下载收费的应用,又没有开通对应的支付方式(例如对应国家地区的信用卡),可以去TB上购买一个Gifts Card充值到账户余额。然后再操作。

2、一些共享AppID的平台

有专门做这个的网站或者论坛帖子,前几年多些。

还有公众号(例如:野泽科技、绝世废柴、DoMiSo),现在以公众号居多。

3、第三方平台安装

使用爱思助手或PP助手直接连接电脑安装对应的应用。

4、怎么获得一个美国区的AppID

这个目前已经有很多方法,而且各种方法都在与时俱进地跟新。可以直接搜索“知乎”等,就有许多可行的方案。   

身份证号码解释,附:18位公民身份证编码规则

发表于 2019-09-21   |   分类于 网络工具

身份证号码解释,附:18位公民身份证编码规则

身份证号码由18位数字组成,你知道它们代表的信息吗?

其中的第一、第二数字表示公民所在地的省份(或自治区、直辖市);第三、第四位数字表示公民所在地的市(或州);第五、第六位数字表示公民所在地的县(或县级市);接下来的8位数字表示公民的出生年、月、日;最后4位数字中的前两位表示当地派出所的编码;倒数第二位表示公民是男性还是女性(男性用单数,女性用双数);最后一位数字是一个随机数,又称为校验码。

大陆的身份证为18位,老的身份证是15位。

关于身份证第18是怎么计算的,原理如下

根据〖中华人民共和国国家标准GB11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

地址码(身份证前六位)表示编码对象常住户口所在县(市、旗、区)的行政区划代码。(所有区域的编码可以到这个网址http://xzqh.mca.gov.cn查询到最新的县及县以上的行政编码资料。)

生日期码(身份证第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。

顺序码(身份证第十五位到十七位)为同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。

校验码(身份证最后一位)是根据前面十七位数字码,按照ISO7064:1983.MOD11-2校验码计算出来的检验码。

第十八位数字的计算方法

1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7910584216379105842

2.将这17位数字和系数相乘的结果相加。

3.用加出来和除以11,看余数是多少?

4.余数只可能有012345678910这11个数字。其分别对应的最后一位身份证的号码为10X98765432。

5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。

例如:某男性的身份证号码是34052419800101001X。我们要看看这个身份证是不是合法的身份证。

首先:我们得出,前17位的乘积和是189

然后:用189除以11得出的结果是17+2/11,也就是说余数是2。

最后:通过对应规则就可以知道余数2对应的数字是X。所以,这是一个合格的身份证号码。


附:18位公民身份证编码规则

18位身份证标准在国家质量技术监督局于1999年7月1日实施的GB11643-1999《公民身份号码》中做了明确规定。GB11643-1999《公民身份号码》为GB11643-1989《社会保障号码》的修订版,其中指出将原标准名称“社会保障号码”更名为“公民身份号码”,另外GB11643-1999《公民身份号码》从实施之日起代替GB11643-1989。公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位校验码。其含义如下:

1.地址码:表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。

2.出生日期码:表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日分别用4位、2位、2位数字表示,之间不用分隔符。

3.顺序码:表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

校验的计算方式:

1.对前17位数字本体码加权求和

公式为:S=Sum(Ai*Wi),i=0,…,16

其中Ai表示第i位置上的身份证号码数字值,Wi表示第i位置上的加权因子,其各位对应的值依次为:7910584216379105842

2.以11对计算结果取模

Y=mod(S,11)

3.根据模的值得到对应的校验码

对应关系为:

Y值:012345678910

校验码:10X98765432

关于18位身份证号码尾数是“X”的解释

居民身份证的号码是按照国家的标准编制的,由18位组成:前六位为行政区划代码,第七至第十四位为出生日期码,第15至17位为顺序码,第18位为校验码。作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-9,都不会出现X,但如果尾号是10,那么就得用X来代替,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准,并且我国的计算机应用系统也不承认19位的身份证号码。X是罗马数字的10,用X来代替10,可以保证公民的身份证符合国家标准。但是我国的居民身份证在升位后,一些人的尾号变成了X,这部分人在工作生活中,例如去银行存取钱、去汽车公司租赁汽车或者报名参加考试等等过程中,往往不被检验者理解,认为是假身份证,这样的误会给很多人的生活带来不便。公安局的同志希望领到X身份证的同志正确理解这个数字的含义,查验身份证的机关和单位更应该清楚这一点。

一个简单身份证号尾号校验算法的PHP实现的过程

<?php
function checkId($id) {
    $len = strlen($id);
    if($len != 18) {
        return 0;
    }
    $a=str_split($id,1);
    $w=array(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2);
    $c=array(1,0,'X',9,8,7,6,5,4,3,2);
    $sum = 0;
    for($i=0;$i<17;$i++){
        $sum= $sum + $a[$i]*$w[$i];
    }
    $r=$sum%11;
    $res=$c[$r];
    //echo "校验位是: ".$res;
    if ($res == $a[17]) {
        return 1;
    } else {
        return 0;
    }
}

  

九酷音乐真实地址解析

发表于 2019-08-03   |   分类于 网络工具

九酷音乐的资源还是比较全的;九酷的历史也比较长,从2002年就有了。
许多其他音乐平台,例如QQ音乐、虾米音乐、网易云音乐上面没有的,这里也可以找到。

缺点就是网页上广告太多,而且页面也不好看。目前也没有PC客户端,手机客户端iOS版一直不能用(数据加载失败,2年多未更新了)。

九酷音乐官网:http://www.9ku.com/

选择一首歌曲,如 http://m.9ku.com/play/86179.htm

其中,86179就是歌曲的id号

真实地址为:

http://mp3.9ku.com/m4a/86179.m4a

http://111.161.71.11/mp3.9ku.com/m4a/86179.m4a

对多维数组进行排序的函数array_multisort

发表于 2019-07-31   |   分类于 技术日记

经常会面临这样的需求,虽然有时候我们可以在数据库查询的时候,直接对数据进行排序,但还是无法满足日益复杂的业务需求。这里边会用到两个函数一个是array_column()函数,这个函数接受三个参数。详情参见这里是从二维数组中抽出一个键的值,作为一个新的数组返回。
另一个是array_multisort()函数,这个函数是一个排序函数,详情参见这里。
它会依照第一个参数数组的排序规则,依照第一个参数数组的值在第三个参数重的位置对第三个参数进行排序。

听不明白吧?听不明白就对了,还是直接看代码来的实在:

$orgin = array(
 array(
    'id' => 5698,
    'first_name' => 'Bill',
    'last_name' => 'Gates',
  ),
 array(
    'id' => 4767,
    'first_name' => 'Steve',
    'last_name' => 'Jobs',
 ),
 array(
    'id' => 3809,
    'first_name' => 'Mark',
    'last_name' => 'Zuckerberg',
  )
);

$idArr = array_column($orgin, 'id');
array_multisort($idArr,SORT_ASC,$orgin);
var_dump($orgin);

这个打印的结果是:

array (size=3)
      0 => 
array (size=3)
  'id' => int 3809
  'first_name' => string 'Mark' (length=4)
  'last_name' => string 'Zuckerberg' (length=10)
  1 => 
array (size=3)
  'id' => int 4767
  'first_name' => string 'Steve' (length=5)
  'last_name' => string 'Jobs' (length=4)
  2 => 
array (size=3)
  'id' => int 5698
  'first_name' => string 'Bill' (length=4)   
  'last_name' => string 'Gates' (length=5)

此函数有点意思。

爬虫获取知乎网页title的方法

发表于 2018-10-17   |   分类于 技术日记

知乎的网页标题title的提取一直有各种问题。可能是知乎自己做了防止被爬虫抓取的。普通的问题详情页和知乎专栏,都提取不到网页title,或者提取到了错误的title。

本文记录了实际可用的方法,分别提取知乎问题详情页的title与知乎专栏页的title和封面图片的提取方法。

知乎问题详情页的title提取

首先看一下源代码

<title>你必讲的笑话是哪个? - 知乎</title><title>知乎 - 有问题上知乎</title>

中间部分源代码省略了。其中有2个title,直接使用正则匹配时,只能匹配到第2个title——“知乎 - 有问题上知乎”,所有页都是这个。

再继续向下面寻找,看到这么一段:
<h1 class="QuestionHeader-title">你必讲的笑话是哪个?</h1>

直接使用正则匹配即可,正则匹配规则为:

<h1\sclass=\"QuestionHeader-title\">([\s\S]+?)<\/h1>

知乎专栏文章页的title提取与封面图片提取

首先看一下源代码

<title>智能闹钟音箱能给自己的商业世界打开一扇窗吗? - 知乎</title><title>知乎 - 有问题上知乎</title>

中间部分源代码省略了。其中有2个title,直接使用正则匹配时,只能匹配到第2个title——“知乎 - 有问题上知乎”,所有页都是这个。

再继续向下面寻找,看到这么一段:
<header class="Post-Header"><h1 class="Post-Title">智能闹钟音箱能给自己的商业世界打开一扇窗吗?</h1>

使用正则匹配也匹配不到。可能是因为知乎专栏页的数据是使用js加载的,网页源代码初始代码中不含有这些数据。

稍微看看知乎专栏网页代码可以发现,如果在浏览器中访问类似这样的专栏文章链接:

https://zhuanlan.zhihu.com/p/42557513

实际会加载下面的文章内容数据 API 链接,知乎专栏页面加载完数据之后才会显示:

https://zhuanlan.zhihu.com/api/posts/42557513

而且返回的数据就是json格式的,可以直接转换为PHP数组,然后根据数组的key值,直接获取需要的字段,然后即可使用。

扩展其他知乎相关页的爬虫抓取

后面的参考链接中里面有一句话说的好:

不管AngularJS还是其它架构,都是服务端的东西,再天花乱坠的服务端架构,到了客户端终究逃不脱HTTP协议,至少目前来说还是如此。

知道用户ID之后可以相机获取:

  1. 获得用户专栏入口
  2. 获得专栏文章信息
  3. 获得专栏文章

参考链接:https://www.zhihu.com/question/24948369/answer/29611724

小结

使用以上各种方法,基本可以解决与知乎相关内容的爬虫爬取相关的问题。

另一篇参考文章:简单PHP实现Pocket抓取知乎专栏文章

1…345…10
isunman

isunman

love IT, love Movie, love Love

98 日志
12 分类
45 标签
RSS
github

Links

知乎
© 2011 - 2025 isunman
由 Hexo 强力驱动
主题 - NexT.Mist
PV -- UV