基于社交网络挖掘公司潜在用户

PabloTaggar 8年前
   <h2><strong>引言</strong></h2>    <p>作为销售人员,在向客户介绍公司的新产品或技术的时候,是否考虑过参考已有的客户成功案例去说服新客户?是否想要去发现某客户可能采用的公司产品?是否希望去挖掘公司潜在的客户?回答是肯定的。挖掘潜在客户一直是每个公司重要的工作之一,准确的发现目标客户并向其推荐其可能使用的产品或方案能够帮助公司实现利益的增长。例如电子商务公司会根据个人浏览商品记录推荐可能感兴趣的其他商品;银行会根据个人的消费记录向其推荐适合的金融产品;娱乐媒体公司会根据个人的观看历史推荐其他相似的影片或音乐。</p>    <p>目前,社交网络在人们的日常生活中扮演着越来越重要的角色,已成为人们交往和获取信息的重要渠道。如何利用其包含的海量的具有时效性的非结构化数据引起了人们的关注。本文在这样的背景下提出一种为公司挖掘潜在客户的方法,从 推ter 和 LinkedIn 等社交媒体上提取信息,利用 Watson API 和 NLTK 分词工具对这些信息进行处理,使用 Python 的主题模型工具包 Gensim 来进行公司之间的相似度计算,最后根据相似度计算结果为公司推荐潜在客户。本文余下章节介绍了具体实现步骤。</p>    <h2><strong>1 从 推ter 上抓取推文</strong></h2>    <p>基于社交网络挖掘公司潜在用户,首先需要在社交网络上搜索公司已有的成功案例。如 IBM 公司在 推ter 中注册了一个名为 IBM Client Voices 的账户,其发布的推文包含了 IBM 的某项产品或技术帮助了某个公司完成了某项任务。</p>    <p>例如:</p>    <p>推文 1: @Runkeeper deploys @IBMcloudant to help blind runner @andadapt manage over 120,000 global data requests per second.</p>    <p>推文 2:" @IBMDB2 with pureScale enables real-time insight into where shipments are in our network, 24/7." Client @nscorp .</p>    <p>推文 3: @VON_Canada partners with #IBM to reduce senior citizen fall rate by a dramatic 72%. Read: http://ibm.co/28IArSG .</p>    <p>我们可以通过 推ter 提供的 API 来提取 IBM Client Voices 账户发布的所有推文。具体的步骤如下:</p>    <h3><strong>1.1 OAuth 授权</strong></h3>    <p>从 1.1 版本开始,使用 推ter API 需要通过 OAuth 授权,授权过程是通过发送 http GET/POST 进行的。</p>    <ol>     <li>注册申请 推ter 的开发者,创建 App,获得开发者的 Key 和 Secret,即 consumer_key & consumer_secret。</li>     <li>用 Http 通过 推ter 提供的 API url + 参数 consumer_key & consumer_secret 到 推ter 的服务器获取 request_token。</li>     <li>用 Http 通过 推ter 提供的 API url + 参数 request_token 到 推ter 服务器请求授权。</li>     <li>授权确认后页面跳转到由你之前注册时填写的 callback_url 为地址前缀的的一个新网址(页面),并获取到 oauth_verifer。</li>     <li>最后,再发送 request_token & oauth_verifier 到 推ter 服务器换取 access_token & access_token_secret, 有了这两个值就可以通过它们进行各种 推ter 操作。</li>    </ol>    <h3><strong>1.2 REST API</strong></h3>    <p>获取 推ter 数据的常用方法是通过 REST API。使用通过 OAuth 授权得到的 tokens,我们的应用可以向 推ter 获取特定的数据。获取 推ter 数据的流程如图 1 所示。</p>    <p><strong>图 1. 获取 推ter 数据的流程</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/5d7a66bb05aea4cc44b18337e1ac2f1b.png"></p>    <p>本文使用 API GET st atuses/user_timeline,来获取某用户所发布的推文。</p>    <p>使用下面语句(本文出现的代码均以 Python 语言编写),可以获得用户 id 为 IBMclientvoices 发布的最新 20 条推文。推文如图 2 所示。</p>    <p>清单 1. 获取到用户最新发布的推文</p>    <pre>  api.user_timeline(id='IBMclientvoices', count=20, max_id=oldest_id-1)</pre>    <p><strong>图 2. 从 推ter 上获取的推文</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/0fbb6983a71d25153ec199ff214d3131.png"></p>    <p>从 推ter 上返回的数据为 JSON 格式,我们从 JSON 返回结果中抽取下列信息(如表 1 所示),并存入数据库中。</p>    <p><strong>表 1. 推文中抽取的信息</strong></p>    <table cellspacing="0">     <thead>      <tr>       <th>id</th>       <th>推文的 id</th>      </tr>     </thead>     <tbody>      <tr>       <td>author</td>       <td>推文的作者</td>      </tr>      <tr>       <td>created_at</td>       <td>推文的创建时间</td>      </tr>      <tr>       <td>text</td>       <td>推文的内容</td>      </tr>      <tr>       <td>user_mentions</td>       <td>推文中@的用户</td>      </tr>      <tr>       <td>hashtags</td>       <td>推文中涉及到 IBM 技术名字</td>      </tr>     </tbody>    </table>    <p>其中 user_mentions 和 hashtags 为我们最为关注的公司名称和产品或方案名称。</p>    <h2><strong>2 从 LinkedIn 提取公司信息</strong></h2>    <p>至此关于公司已有的成功案例信息提取完毕,但是 推ter 中包含的公司信息有限,所以需要从其他的数据源中提取更多的关于各个公司的信息来完成进一步的数据挖掘,推荐工作。社交媒体 LinkedIn 中包含了更多的关于公司的信息,本文接下来介绍如何提取 LinkedIn 中的相关信息。</p>    <h3><strong>2.1 获取授权</strong></h3>    <p>我们使用 LinkedIn 支持的 OAuth 2.0 协议来进行授权。授权成功后,就可以通过调用 REST API 来与服务器进行交互。</p>    <ol>     <li>首先在 LinkedIn 开发者网站 <p>创建一个应用。</p> <p>创建一个应用后,会获得一组验证秘钥,包括客户端编号(Client ID),以及客户端密码(Client Secret)。然后需要在创建的应用中添加授权重定向网址 Authorized Redirect URLs。</p> </li>     <li> <p>加载 WebView 获得授权码。</p> <p>打开 WebViewController.swift 文件,添加必要的参数。当这些必要的参数都添加成功后,我们就在 WebView 中登录了 LinkedIn 账号,请求加载成功后,LinkedIn 服务器就会返回一个授权码。</p> </li>     <li> <p>交换授权码,获取 Access Token。</p> <p>通过 Access Token,我们可以向 LinkedIn 服务器发起授权请求,并通过 GET 或 POST 请求获取信息。下图展示了如何通过提供 Access Token 发起授权请求,并调用 API。</p> </li>    </ol>    <p><strong>清单 1. 通过 Access Token 发起授权请求</strong></p>    <pre>  application = LinkedInApplication(token = 'Your AccessToken')</pre>    <h3><strong>2.2 调用 API 获取公司信息</strong></h3>    <p>我们使用 LinkedIn 提供的 API LinkedInApplication 来进行关键字搜索。以从 推ter 推文中获取的公司名称为关键字,搜索所有相关的公司的信息。</p>    <p>该 API 所能返回与关键字相关的公司的多维度信息,包括 ID,公司名称,公司网页 URL,公司所处行业,公司介绍,公司领域,公司类型和规模等。</p>    <p>我们会从 API 返回的公司集合中,选择返回结果中的第 1 个公司,即相似度最高的一个公司,与 推ter 推文中获取的公司名称再进行下一步的匹配。</p>    <p><strong>清单 2. 调用 API 获取公司信息</strong></p>    <pre>  def link_search_comp(keyword):  result_from_linkedin = application.search_company(selectors=[{'companies':['id',  'name', 'websiteurl','industries','description','specialties',   '推ter-id','company-type','employee-count-range']}], params={'keywords':keyword})       if (result_from_linkedin['companies']['_total']>0):            if(result_from_linkedin['companies']['values'][0].has_key('websiteUrl')==False):                    result_from_linkedin['companies']['values'][0]['websiteUrl']=''           return result_from_linkedin['companies']['values'][0]       return ''</pre>    <h3><strong>2.3 匹配公司</strong></h3>    <p>为了绝对匹配 推ter 推文中所提到的公司与 LinkedIn 中的公司,我们采用匹配公司名称和 URL 域名相结合的方式。首先,以 推ter 推文中涉及到的公司 name 域为关键字,通过该名称在 Linkedin 中搜索,若搜索结果中的公司名称和输入的关键字完全匹配,则为公司匹配成功;若不完全匹配,则进一步判断 推ter 和 Linkedin 公司的 URL 域名是否相同,同时,为了避免因为 推ter 中个人使用公司 URL 这种情况的存在而造成最终公司匹配错误,还需要判断输入关键字和搜索结果中公司名称的字符串相似度是否达到给定阈值,以上两个条件同时满足时,公司匹配成功,否则,匹配失败。若通过公司名称方式匹配失败,则继续通过 URL 域名方式进行搜索,该方式将 推ter 中公司 URL domain 中的域作为关键字在 Linkedin 中进行搜索,若搜索结果中公司的 URL 域名和 推ter 中公司的 URL 域名相同,则匹配成功,否则失败。利用上述匹配方法,通过统计可得 推ter 推文中所提到的公司,约 60%可在 LinkedIn 中一一匹配并能够提取到其进一步的具体信息。</p>    <p><strong>清单 3. 匹配公司</strong></p>    <pre>  def link_compare_match(linkedin_result,推ter_result,method):       linkedin_domain = get_format_domain(linkedin_result['websiteUrl'])       推ter_domain = 推ter_result.urls       if (method == 'name'):             if (推ter_domain==linkedin_domain):                   return YES       elif(method=='domain'):              if(linkedin_result['name'] == 推ter_result.name):                     return YES  elif (推ter_domain==linkedin_domain and name_match(linkedin_result['name'],  推ter_result.name)==True):                     return YES       return NO</pre>    <p>对于这些匹配成功的公司,我们有了更详尽的数据,包括公司所属行业,专注的领域,公司规模,公司描述等等。通过这些丰富的信息,我们可计算得出不同公司之间的相似度,通过相似度来挖掘潜在客户。</p>    <h2><strong>3 推荐算法</strong></h2>    <p>通过上面两步操作,我们获得了公司的描述(description),所属行业(industry)以及公司的专属领域(specialties),这几个特性反映了公司的大部分特征。因此,本文可以依据这这些特征来计算公司间的相似度,通过公司特征间的匹配来进行公司间的匹配。为了提高公司之间的匹配度,本文通过 Watson 提供的关键字提取 API 来对公司的 description 域进行关键字提取,并和 specialties 域合并成为最终进行相似度匹配的文本信息。之后通过 Python 分词工具包 NLTK 对合并后的文本分析,得到该领域公司信息的语料库。最后通过 Gensim 工具中的 LSI 模型进行相似度计算。下面首先简单介绍一下 LSI 模型。</p>    <h3><strong>3.1 LSI 模型</strong></h3>    <p>潜在语义分析(LSA)又被称作潜在语义索引(LSI),是一种在自然语言处理中用到的技术,其将大量文本表示成矩阵,矩阵的每一行表示一个词,每一列表示一篇文档,矩阵的元素可以为词频或 TF-IDF 值。LSA 采用奇异值分解(SVD)对原始矩阵进行降维,得到原始矩阵的低阶近似矩阵。之后,其使用余弦相似度公式计算两个文本的相似度。通过 LSA 模型,可以很准确的计算出两个文本信息之间的相似度。由于本文中的公司信息中有足够的、包含公司特征的文本信息,所以本文采用 LSI 模型来进行公司之间的相似度计算。</p>    <h3><strong>3.2 关键字提取</strong></h3>    <p>为了使用 Watson API 进行关键字提取,需要在 Bluemix 平台创建 AlchemyAPI 服务,服务创建完毕后会获得一个认证秘钥 API_KEY,使用该秘钥才可以进行关键字提取 API 的调用。AlchemyAPI 提供了一组服务,支持企业和开发人员构建相关应用程序,本文用到的是其中的 AlchemyLanguage 服务。</p>    <p>AlchemyLanguage 是通过自然语言处理提供文本分析的 API 集合。借助 AlchemyLanguage,可以实现 Keyword Extraction、Entity Extraction、Sentiment Extraction、Emotion Analysis、Concept Tagging、Taxonomy Classification 等。本文使用了 Keyword Extraction 功能。</p>    <p>AlchemyLanguage 的具体使用步骤为:</p>    <ol>     <li>获取关键字提取服务 <p>清单 5. 获取关键字提取服务</p> <pre>  alchemy_language=AlchemyLanguageV1(api_key='Your APIKEY')</pre> </li>     <li>指定输出结果域,本文只需要提取 keyword 域即可 <p>清单 6. 提取 keyword 域</p> <pre>  combined_operations = ['keyword']</pre> </li>     <li>提取关键字 <p>清单 7. 提取关键字</p> <pre>  result = alchemy_language.combined(text=description, extract=combined_operations)</pre> </li>    </ol>    <h3><strong>3.3 NLTK 分词工具</strong></h3>    <p>NLTK 是基于 Python 的分词工具,在使用 Gensim 计算相似度之前,必须要对公司关键字提取后的结果进行分词处理,主要包括以下步骤:对文档 text 分词并小写化、设置停用词及标点符号集、去停用词及标点符号。</p>    <p>经过以上分词处理后,对指定领域内的每个公司,合并 description 的关键字和 specialties 成为 text,对每个公司重复上述步骤,最终得到某行业内(industry)公司信息的语料库,该语料库作为 Gensim 工具的输入。</p>    <h3><strong>3.4 通过 Gensim 工具进行相似度计算</strong></h3>    <p>本文使用了 Python 版的 Gensim 工具,并以 4.4 节获得的公司信息语料库作为 Gensim 工具的输入。令 texts 为指定公司信息语料库,首先通过 texts 抽取一个"词袋(bag-of-words)",将 texts 的 token 映射为 id,方法如下:</p>    <p>清单 8. texts 的 token 映射为 id 的方法</p>    <pre>  dictionary = corpora.Dictionary(texts)</pre>    <p>然后将用字符串表示的文档转换为用 id 表示的文档向量:</p>    <p>清单 9. 用 id 表示的文档向量</p>    <pre>  corpus = [dictionary.doc2bow(text) for text in texts]</pre>    <p>有了这些信息,就可以基于这些信息计算一个 TF-IDF 模型:</p>    <p>清单 10. 计算 TF-IDF 模型</p>    <pre>  tfidf = models.TfidfModel(corpus)</pre>    <p>基于这个 TF-IDF 模型,就可以将上述词频表示的文档向量表示为一个用 TF-IDF 值表示的文档向量:</p>    <p>清单 11. 用 TF-IDF 值表示的文档向量</p>    <pre>  corpus_tfidf = tfidf[corpus]</pre>    <p>有了 tf-idf 值表示的文档向量,就可以训练一个 LSI 模型,并建立索引,在本文将 topic 数设置为 10,即将 TF-IDF 语料转化为一个潜在 10-D 空间:</p>    <p>清单 12. 训练 LSI 模型</p>    <pre>  lsi = models.LsiMoidel(corpus_tfidf,id2word=dictionary,num_topics=10)  index = similarities.MatrixSimilarity(lsi[corpus])</pre>    <p>基于 LSI 模型的索引建立完毕,通过 LSI 模型可以将公司 description 关键字和 specialties 组成的 query_word 映射到 10 个 topic 主题模型空间上,然后和其他公司计算相似度并存于 sims 列表中:</p>    <p>清单 13. 计算和其它公司的相似度并存在 sims 列表中</p>    <pre>  query_bow = dictionary.doc2bow(query_words)  query_lsi = lsi[query_bow]  sims = index[query_lsi]</pre>    <h2><strong>4 系统推荐流程图</strong></h2>    <p>至此,我们可以通过 推ter,LinkedIn 进行公司信息提取,信息处理,以及使用 LSI,奇异值分解(SVD)等方法计算公司间的相似度,并完成潜在客户的挖掘与推荐。具体的推荐流程如图 3 所示。</p>    <p><strong>图 3. 系统推荐流程图</strong></p>    <p><img src="https://simg.open-open.com/show/5cdb35dab932cc05b175a217dd6618d8.png"></p>    <h2><strong>5 为用户推荐 IBM 产品</strong></h2>    <p>由推文的提取过程可知,IBM Client Voice 发表的推文中包含 IBM 产品及其使用客户,并可在数据库中获取指定用户使用的 IBM 产品。为了给指定用户推荐 IBM 的其他产品,首先需要获取该用户所属行业内的其他用户,然后通过上述步骤计算该用户与同行业内的其他用户的相似度,并将相似度达到某个阈值的用户所使用的 IBM 产品推荐给该公司。具体的实现界面如图 4 所示:</p>    <p><strong>图 4. IBM 产品推荐结果</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/23f06a2e6db0a99511c268f87c357840.png"></p>    <h2><strong>6 为 IBM 产品挖掘潜在客户</strong></h2>    <p>由于一个 IBM 产品可能有多个用户使用,为了给某个 IBM 产品挖掘潜在客户,必须获取当前使用了该产品的用户集,对于与该用户集中的用户相似度达到某个阈值的用户即可作为该产品的潜在客户。所以,对该用户集中的每个用户,计算与其同行业内用户的相似度,从而获得一个潜在客户集。具体的实现界面如图 5 所示:</p>    <p><strong>图 5. 潜在客户推荐结果</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/777ffb816b05628532db0f641c82718c.png"></p>    <p> </p>    <h2><strong>7 总结</strong></h2>    <p>推荐已经广泛使用于电子商务、电影和视频网站、个性化音乐网络电台、社交网络、网络公开课等领域,但基于社交网络为公司推荐潜在客户的实践却很少见。挖掘潜在客户是所有公司的强烈需求之一,因此,本文所述的推荐系统具有很强的实践意义。为进一步提高潜在客户推荐的准确性,接下来会关注于从更多的社交网络中挖掘更多的数据源来丰富以往的成功案例,并挖掘关于各个公司更多的信息来提高相似度计算的准确性。</p>    <h2><strong>参考资源</strong></h2>    <ul>     <li>查看 <a href="/misc/goto?guid=4959724351649950036" rel="nofollow,noindex">alchemyapi 介绍文档</a> ,了解如何使用该服务。</li>     <li>查看 <a href="/misc/goto?guid=4959724351735512260" rel="nofollow,noindex">Bluemix 文档中心</a> ,了解如何使用 Bluemix 平台及其更多的服务。</li>     <li>参考 <a href="/misc/goto?guid=4959648875953402206" rel="nofollow,noindex">潜在语义分析(Latent semantic analysis)Wiki 页面</a> ,了解更多关于 LSA 的内容。</li>     <li>参考 <a href="/misc/goto?guid=4959724351858441046" rel="nofollow,noindex">奇异值分解(Singular value decomposition)Wiki 页面</a> ,了解更多关于 SVD 的内容。</li>     <li>参考 <a href="/misc/goto?guid=4958961115246865804" rel="nofollow,noindex">TF-IDF Wik</a> <a href="/misc/goto?guid=4958961115246865804" rel="nofollow,noindex">i 页面</a> ,了解更多关于 TF-IDF 的内容。</li>     <li>查看 <a href="/misc/goto?guid=4959724351973285066" rel="nofollow,noindex">推ter 开发者页面</a> ,了解如何开发基于 推ter 的应用程序。</li>     <li>查看 <a href="/misc/goto?guid=4958345672837445768" rel="nofollow,noindex">Linkedi</a> <a href="/misc/goto?guid=4958345672837445768" rel="nofollow,noindex">n 开发</a> <a href="/misc/goto?guid=4958345672837445768" rel="nofollow,noindex">者页面</a> ,了解如何开发基于 Linkedin 的应用程序。</li>    </ul>    <p> </p>    <p>来自:http://www.ibm.com/developerworks/cn/analytics/library/ba-cn-socialmedia-customermining/index.html?ca=drs-</p>    <p> </p>