分享

一些门户或平台网站的数据获取与分析

 quasiceo 2015-03-09
1. 为了推广,有目的地爬一些邮件,群发广告;
2. 做一个博客管理软件,同时管理新浪、网易、搜狐的个人博客;
3. 淘宝商家在推广一个新宝贝时候,根据关键词的热度对它进行标签标示;
4. 朋友参与一个网络投票活动,可能帮他刷点票;
5. 。。。。。

等等,这些东东,所谓“网络应用”乍一看没什么技术含量,当你通过网络得知“某一款淘宝客工具有近万用户,每个用户每月都要支付***”,一款商务快车(制造网络垃圾)的东东是那么地受推崇——你或许会感叹一声,现在的web啊。。。

Well,言归正传,要解决类似的需求,我抛个砖,大家可以拍砖,当然更欢迎补充——

1. 准备好你的Tools Box:
        喜欢Web Spider的,去open-open.com上找几个热门的,通过文档学习这些东东偶就不累述了;
        寻找一个自己熟悉的脚本语言(灵活点在这里好处你会慢慢发现的)——推荐PHP Ruby/Python——如果你和我一样有点少数人倾向,Groovy/Scala也不错;
        浏览器的辅助,这个在一些复杂的http交互环境中更显得重要——推荐Firefox的HttpFox,还有就是Chrome自带的js调试面板和Network面板;

2. 编程语言上的工具:
        这些需求好多都是在模拟Http请求,所以一个Http Client之类的库是不可少的——有的童鞋会想到HttpUnit(Java)的可以直接提供模拟浏览器文档模型和事件驱动,但当你用过你就知道,开源的js库能做到跨浏览器的还真不多。。。
        更好的封装——CURL工具或Restful Client之类的库,这个看个人喜好,自己通过文档一样可以在HttpClient上弄出比如权限认证之类的。。。
        和具体需求相关的一些专用工具或网络资源——比如Sina Weibo SDK,TaobaoClient等,一些代理IP列表。。。

3. 一个好的文本编辑器——你可以称它为一个IDE,但是对于脚本来说,像Eclipse/NetBeans/VS之类的,不如EditPlus Vim Notepad++ MadEdit Geany UltraEdit来的方便——别说你还没能熟练地运用其中的一款,恭喜你,你作为一个Coder还有很大的提升空间(题外话)——但当你真正熟悉其中一个时,你会爱死他的。。。


我以前的博客写过一些关于网络抓取、代理投票、门户网站登录发博等文章了,总得来说,其内容零零散散,代码也片片的,下面我以最近的一个淘宝上的需求为例说明下具体解决过程——

1. 需求:作为一个卖家,获取所有的会员信息记录和交易记录,从中分析出Email和手机号,然后进行邮件群发和短信群发以作推广。
2. 背景:如果你没接触过淘宝卖家的那些后台功能,没关系,我简单说下——Taobao提供的SDK中Email\手机号在API文档里是搞不出来的。Taotao提供一个发站内信和Email的工具,价格好像每封2分,如果会员有10000个,这个功能如果自己能搞了,可以省下200快钱呢!而且Taobao发站内信还做了时间间隔的限制(一段时间内至多发几次)
3. 思路:模拟登陆,模拟请求获取源码,然后分析——太俗套了,本质上还是Spider,哈哈,BS下自己。。。
4. 过程:我只提几个——
        Taobao的用户密码:一般这帮网站都会用一堆加了密的Js对密码再进行加密然后再提交的,这个时候HttpFox就很有帮助了,具体使用有个小技巧——在Post Data里Copy All Rows然后再用正则替换下,就成了一个标准的请求参数Map了——别真一个个手工去敲;还有就是好多Form都有Token;
5. 参考:http://www./topic/593801
6. 代码(进行修改和整合的)——如果你想用多个类,更职责分明或更优美一点的话,一点都不是什么难事儿。

       

  1. package app

  2. import groovy.sql.Sql

  3. import org.apache.http.HttpEntity
  4. import org.apache.http.HttpResponse
  5. import org.apache.http.client.ClientProtocolException
  6. import org.apache.http.client.HttpClient

  7. import org.apache.http.params.HttpProtocolParams

  8. import org.apache.http.client.methods.*
  9. import org.apache.http.impl.client.DefaultHttpClient
  10. import org.apache.http.entity.StringEntity
  11. import org.apache.http.util.EntityUtils

  12. import org.apache.http.client.entity.UrlEncodedFormEntity
  13. import org.apache.http.NameValuePair
  14. import org.apache.http.message.BasicNameValuePair

  15. def static String parseResp(HttpEntity respEntity){
  16.         String encoding = 'gbk'
  17.         StringBuffer sb = new StringBuffer()
  18.         BufferedReader reader = new BufferedReader(
  19.                 new InputStreamReader(respEntity.getContent(), encoding))
  20.         String line = null
  21.         while ((line = reader.readLine()) != null) {   
  22.                 sb.append(line)
  23.                 sb.append("\n")
  24.         }
  25.         return sb.toString()
  26. }

  27. def static String get(HttpClient httpclient, String host, String targetURL){
  28.         HttpGet gg = new HttpGet(host)
  29.         gg.setURI(new URI(targetURL))

  30.         HttpResponse response = httpclient.execute(gg)
  31.         HttpEntity respEntity = response.getEntity()

  32.         String rr = parseResp(respEntity)

  33.         if (respEntity != null) {
  34.                 respEntity.consumeContent()
  35.         }

  36.         return rr
  37. }

  38. def static String post(HttpClient httpclient, String targetURL, Map paramList){
  39.         String urlEncoding = 'gbk'
  40.         HttpPost httppost = new HttpPost(targetURL)

  41.         List<NameValuePair> nvps = new ArrayList<NameValuePair>()
  42.         if(paramList){
  43.                 paramList.each{k, v ->
  44.                         nvps.add(new BasicNameValuePair(k, v))
  45.                 }
  46.         }
  47.         httppost.setEntity(new UrlEncodedFormEntity(nvps, urlEncoding))

  48.         HttpResponse response = httpclient.execute(httppost)
  49.         HttpEntity respEntity = response.getEntity()

  50.         String rr = parseResp(respEntity)

  51.         if (respEntity != null) {
  52.                 respEntity.consumeContent()
  53.         }
  54.         return rr
  55. }
  56. // ******************************

  57. String host = 'https://login.taobao.com/'
  58. // TODO
  59. String uu = '你的账户名'
  60. String seller_id = '你的卖家ID' // 这个通过HttpWatch看下就知道

  61. // 这2个通过HttpWatch看下就知道
  62. String pp = 'XXX' // 加过密的密码
  63. String xxtid = 'XOR_1_000000000000000000000000000000_63584557457974767E740B7F' // tid

  64. // 表示全局的一个表单token
  65. String token = ''

  66. // 一共就一个实例
  67. HttpClient httpclient = new DefaultHttpClient()
  68. // 如果不想把数据保存到数据库,这里也没什么事儿了
  69. Map p = [
  70.         url:'jdbc:h2:~/h2-data/taobao_member',
  71.         u:'u',
  72.         p:'p',
  73.         driver:'org.h2.Driver'
  74. ]
  75. Sql db = Sql.newInstance(p.url, p.u, p.p, p.driver)

  76. // 取得登陆token
  77. String r1 = get(httpclient, host,
  78.         'https://login.taobao.com/member/login.jhtml')
  79. (r1 =~ /_tb_token_' type='hidden' value='([^']+)'/).each{
  80.         token = it[1]
  81. }

  82. // 登陆Post的表单参数
  83. Map params = [
  84.         TPL_username:uu,
  85.         TPL_password:pp,
  86.         TPL_redirect_url:'',
  87.         tid:xxtid,

  88.         _tb_token_:token,
  89.         action:'Authenticator',
  90.         event_submit_do_login:'anything',
  91.         from:'tb',
  92.         fc:'2',
  93.         style:'default',
  94.         support:'000001',
  95.         CtrlVersion:'1,0,0,7',
  96.         loginType:'4',
  97.         minititle:'',
  98.         minipara:'',
  99.         pstrong:'',
  100.         longLogin:'-1',
  101.         llnick:'',
  102.         sign:'',
  103.         need_sign:'',
  104.         isIgnore:'',
  105.         popid:'',
  106.         callback:'',
  107.         guf:'',
  108.         not_duplite_str:'',
  109.         need_user_id:'',
  110.         poy:'',
  111.         gvfdcname:'10',
  112.         from_encoding:''
  113. ]
  114. // 登陆
  115. post(httpclient, 'https://login.taobao.com/member/login.jhtml', params)


  116. // 根据会员关系管理的会员列表获取会员信息
  117. //String rr = get(httpclient, host, 'http://ecrm.taobao.com/member/member_list.htm')
  118. //(rr =~ /_tb_token_' type='hidden' value='([^']+)'/).each{
  119. //        token = it[1]
  120. //}
  121. //
  122. //Map params_member_ll = [
  123. //        _tb_token_: token,
  124. //        page: '1',
  125. //        sellerId: seller_id,
  126. //        buyerId: '',
  127. //        maxAmount: '0',
  128. //        minAmount: '0',
  129. //        maxCount: '0',
  130. //        minCount: '0',
  131. //        memberInfo: '',
  132. //        buyerNick: '',
  133. //        relation: '0',
  134. //        minTradeCount: '',
  135. //        maxTradeCount: '',
  136. //        minTradeAmount: '',
  137. //        maxTradeAmount: '',
  138. //        startTradeTime: '',
  139. //        endTradeTime: '',
  140. //        status: '0'
  141. //]
  142. //
  143. //int max_page = 100
  144. //(1..max_page).each{
  145. //        List member_ll = []
  146. //
  147. //        params_member_ll.page = it + ''
  148. //        String rr2 = post(httpclient, 'http://ecrm.taobao.com/member/member_list.htm', params_member_ll)
  149. //
  150. //        // <a href="http://ecrm.taobao.com/member/member_detail.htm?seller_id=&buyer_id=372068812&status=1">837821089_88</a>
  151. //        (rr2 =~ /<a href="(http:\/\/ecrm\.taobao\.com\/member\/member_detail\.htm\?seller_id=(\d+)&buyer_id=(\d+)&status=\d)">([^<]+)<\/a>/).each{
  152. //                Map item = [:]
  153. //                item.url = it[1].replaceAll(/&/, '&')
  154. //                item.seller_id = it[2]
  155. //                item.buyer_id = it[3]
  156. //                item.nick = it[4]
  157. //
  158. //                member_ll << item
  159. //        }
  160. //
  161. //        member_ll.each{
  162. //                String dd = get(httpclient, host, it.url)
  163. //                (dd =~ /买家姓名:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  164. //                        it.name = gg[1]
  165. //                }
  166. //                (dd =~ /买家性别:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  167. //                        it.gender = gg[1].trim()
  168. //                }
  169. //                (dd =~ /买家生日:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  170. //                        it.birth = gg[1]
  171. //                }
  172. //                (dd =~ /交易量(笔):<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  173. //                        it.transf_num = gg[1]
  174. //                }
  175. //                (dd =~ /交易额(元):<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  176. //                        it.transf_amount = gg[1]
  177. //                }
  178. //                (dd =~ /省份:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  179. //                        it.prov = gg[1]
  180. //                }
  181. //                (dd =~ /城市:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  182. //                        it.prov = gg[1]
  183. //                }
  184. //                (dd =~ /城市:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  185. //                        it.city = gg[1]
  186. //                }
  187. //                (dd =~ /电子邮箱:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  188. //                        it.email = gg[1]
  189. //                }
  190. //                (dd =~ /b_red_(\d+)\.gif/).each{gg ->
  191. //                        it.credit = gg[1]
  192. //                }
  193. //        }
  194. //        member_ll.each{
  195. //                List args = [it.buyer_id, it.nick, it.name, it.gender,
  196. //                        it.prov, it.city, it.email, it.credit]
  197. //                db.executeInsert("insert into taobao_member(uid, nick, name, gender, " +
  198. //                        "prov, city, email, credit) values (?,?,?,?,?,?,?,?)", args)
  199. //
  200. //                println 'Add ok for ' + it.nick
  201. //        }
  202. //}

  203. // 根据成功交易获取 联系人 手机 和收货地址
  204. Map trade_param_ll = [
  205.         event_submit_do_query:'1',
  206.         user_type:'1',
  207.         pageNum:'1',
  208.         isArchive:'false',
  209.         order:'desc',
  210.         order_type:'orderList',
  211.         isArchiveDefault:'0',
  212.         isQueryMore:'false',
  213.         select_shop_name:'',
  214.         isOwnOfficialShop:'false',
  215.         sellerNumID:seller_id,
  216.         '_fmt.q._0.a':'',
  217.         '_fmt.q._0.bi':'',
  218.         '_fmt.q._0.biz':'00:00',
  219.         '_fmt.q._0.bizo':'',
  220.         '_fmt.q._0.bizor':'00:00',
  221.         '_fmt.q._0.b':'',
  222.         '_fmt.q._0.au':'SUCCESS',
  223.         '_fmt.q._0.c':'ALL',
  224.         '_fmt.q._0.bizord':'',
  225.         '_fmt.q._0.l':'ALL',
  226.         '_fmt.q._0.t':'ALL',
  227.         '_fmt.q._0.sh':'All',
  228.         action:'itemlist/QueryAction',
  229.         fromTag:'true'       
  230. ]

  231. // TODO 这个交易的是总页数
  232. int max_page = 100
  233. (1..max_page).each{
  234.         List member_ll = []

  235.         trade_param_ll.pageNum = it + ''
  236.         String rr2 = post(httpclient, 'http://trade.taobao.com/trade/itemlist/list_sold_items.htm', trade_param_ll)

  237.         // <a href="http://trade.taobao.com/trade/detail/trade_item_detail.htm?bizOrderId=45055548819742&his=false" class="detail-link" target="_blank">详情</a>
  238.         (rr2 =~ /<a href="(http:\/\/trade\.taobao\.com\/trade\/detail\/trade_item_detail\.htm[^"]+)" class="detail-link" target="_blank">/).each{
  239.                 Map item = [:]
  240.                 item.url = it[1]
  241.                 member_ll << item
  242.         }

  243.         member_ll.each{
  244.                 String dd = get(httpclient, host, it.url)
  245.                 (dd =~ /收货地址:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->
  246.                         it.info = gg[1]
  247.                 }
  248.                 (dd =~ /<span class="nickname">([^<]+)<\/span>/).each{gg ->
  249.                         it.nick = gg[1]
  250.                 }
  251.         }
  252.         member_ll.each{
  253.                 def item = db.firstRow("select id from taobao_member_trade where info = ?", [it.info])
  254.                 if(item){
  255.                         println 'Skip trade for ' + it.nick
  256.                 }else{
  257.                         List args = [it.info, it.nick]
  258.                         db.executeUpdate("insert into taobao_member_trade(info, nick) values (?,?)", args)
  259.                         println 'Add trade ok for ' + it.nick
  260.                 }

  261.         }
  262. }

  263. httpclient.getConnectionManager().shutdown()

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多