读书人

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

发布时间: 2012-09-02 21:00:34 作者: rapoo

一些门户或平台网站的数据获取与分析——以淘宝为例

RT——在大家做网站或GUI的业余时间,可能你会碰到这样的需求——

?

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.iteye.com/topic/593801

6. 代码(进行修改和整合的)——如果你想用多个类,更职责分明或更优美一点的话,一点都不是什么难事儿。

?

package appimport groovy.sql.Sqlimport org.apache.http.HttpEntityimport org.apache.http.HttpResponseimport org.apache.http.client.ClientProtocolExceptionimport org.apache.http.client.HttpClientimport org.apache.http.params.HttpProtocolParamsimport org.apache.http.client.methods.*import org.apache.http.impl.client.DefaultHttpClientimport org.apache.http.entity.StringEntityimport org.apache.http.util.EntityUtilsimport org.apache.http.client.entity.UrlEncodedFormEntityimport org.apache.http.NameValuePairimport org.apache.http.message.BasicNameValuePairdef static String parseResp(HttpEntity respEntity){String encoding = 'gbk'StringBuffer sb = new StringBuffer()BufferedReader reader = new BufferedReader(new InputStreamReader(respEntity.getContent(), encoding)) String line = nullwhile ((line = reader.readLine()) != null) {   sb.append(line)sb.append("\n")}return sb.toString()}def static String get(HttpClient httpclient, String host, String targetURL){HttpGet gg = new HttpGet(host)gg.setURI(new URI(targetURL))HttpResponse response = httpclient.execute(gg)HttpEntity respEntity = response.getEntity()String rr = parseResp(respEntity)if (respEntity != null) {respEntity.consumeContent()}return rr}def static String post(HttpClient httpclient, String targetURL, Map paramList){String urlEncoding = 'gbk'HttpPost httppost = new HttpPost(targetURL)List<NameValuePair> nvps = new ArrayList<NameValuePair>()if(paramList){paramList.each{k, v ->nvps.add(new BasicNameValuePair(k, v))}}httppost.setEntity(new UrlEncodedFormEntity(nvps, urlEncoding))HttpResponse response = httpclient.execute(httppost)HttpEntity respEntity = response.getEntity()String rr = parseResp(respEntity)if (respEntity != null) {respEntity.consumeContent()}return rr}// ******************************String host = 'https://login.taobao.com/'// TODOString uu = '你的账户名'String seller_id = '你的卖家ID' // 这个通过HttpWatch看下就知道// 这2个通过HttpWatch看下就知道String pp = 'XXX' // 加过密的密码String xxtid = 'XOR_1_000000000000000000000000000000_63584557457974767E740B7F' // tid// 表示全局的一个表单tokenString token = ''// 一共就一个实例HttpClient httpclient = new DefaultHttpClient()// 如果不想把数据保存到数据库,这里也没什么事儿了Map p = [url:'jdbc:h2:~/h2-data/taobao_member', u:'u', p:'p', driver:'org.h2.Driver']Sql db = Sql.newInstance(p.url, p.u, p.p, p.driver)// 取得登陆tokenString r1 = get(httpclient, host, 'https://login.taobao.com/member/login.jhtml')(r1 =~ /_tb_token_' type='hidden' value='([^']+)'/).each{token = it[1]}// 登陆Post的表单参数Map params = [TPL_username:uu, TPL_password:pp, TPL_redirect_url:'',tid:xxtid, _tb_token_:token, action:'Authenticator', event_submit_do_login:'anything', from:'tb', fc:'2', style:'default', support:'000001', CtrlVersion:'1,0,0,7', loginType:'4',minititle:'', minipara:'', pstrong:'', longLogin:'-1', llnick:'', sign:'', need_sign:'', isIgnore:'', popid:'', callback:'', guf:'', not_duplite_str:'', need_user_id:'', poy:'', gvfdcname:'10', from_encoding:'']// 登陆post(httpclient, 'https://login.taobao.com/member/login.jhtml', params)// 根据会员关系管理的会员列表获取会员信息//String rr = get(httpclient, host, 'http://ecrm.taobao.com/member/member_list.htm')//(rr =~ /_tb_token_' type='hidden' value='([^']+)'/).each{//token = it[1]//}////Map params_member_ll = [//_tb_token_: token, //page: '1', //sellerId: seller_id, //buyerId: '', //maxAmount: '0', //minAmount: '0', //maxCount: '0', //minCount: '0', //memberInfo: '', //buyerNick: '', //relation: '0', //minTradeCount: '', //maxTradeCount: '', //minTradeAmount: '', //maxTradeAmount: '', //startTradeTime: '', //endTradeTime: '', //status: '0'//]////int max_page = 100//(1..max_page).each{//List member_ll = []////params_member_ll.page = it + ''//String rr2 = post(httpclient, 'http://ecrm.taobao.com/member/member_list.htm', params_member_ll)////// <a href="http://ecrm.taobao.com/member/member_detail.htm?seller_id=&buyer_id=372068812&status=1">837821089_88</a>//(rr2 =~ /<a href="(http:\/\/ecrm\.taobao\.com\/member\/member_detail\.htm\?seller_id=(\d+)&buyer_id=(\d+)&status=\d)">([^<]+)<\/a>/).each{//Map item = [:]//item.url = it[1].replaceAll(/&/, '&')//item.seller_id = it[2]//item.buyer_id = it[3]//item.nick = it[4]////member_ll << item//}////member_ll.each{//String dd = get(httpclient, host, it.url)//(dd =~ /买家姓名:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.name = gg[1]//}//(dd =~ /买家性别:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.gender = gg[1].trim()//}//(dd =~ /买家生日:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.birth = gg[1]//}//(dd =~ /交易量(笔):<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.transf_num = gg[1]//}//(dd =~ /交易额(元):<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.transf_amount = gg[1]//}//(dd =~ /省份:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.prov = gg[1]//}//(dd =~ /城市:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.prov = gg[1]//}//(dd =~ /城市:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.city = gg[1]//}//(dd =~ /电子邮箱:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->//it.email = gg[1]//}//(dd =~ /b_red_(\d+)\.gif/).each{gg ->//it.credit = gg[1]//}//}//member_ll.each{//List args = [it.buyer_id, it.nick, it.name, it.gender, //it.prov, it.city, it.email, it.credit]//db.executeInsert("insert into taobao_member(uid, nick, name, gender, " + //"prov, city, email, credit) values (?,?,?,?,?,?,?,?)", args)////println 'Add ok for ' + it.nick//}//}// 根据成功交易获取 联系人 手机 和收货地址Map trade_param_ll = [event_submit_do_query:'1',user_type:'1',pageNum:'1',isArchive:'false',order:'desc', order_type:'orderList', isArchiveDefault:'0', isQueryMore:'false', select_shop_name:'', isOwnOfficialShop:'false', sellerNumID:seller_id, '_fmt.q._0.a':'', '_fmt.q._0.bi':'', '_fmt.q._0.biz':'00:00', '_fmt.q._0.bizo':'', '_fmt.q._0.bizor':'00:00', '_fmt.q._0.b':'', '_fmt.q._0.au':'SUCCESS', '_fmt.q._0.c':'ALL', '_fmt.q._0.bizord':'', '_fmt.q._0.l':'ALL', '_fmt.q._0.t':'ALL', '_fmt.q._0.sh':'All', action:'itemlist/QueryAction', fromTag:'true']// TODO 这个交易的是总页数int max_page = 100(1..max_page).each{List member_ll = []trade_param_ll.pageNum = it + ''String rr2 = post(httpclient, 'http://trade.taobao.com/trade/itemlist/list_sold_items.htm', trade_param_ll)// <a href="http://trade.taobao.com/trade/detail/trade_item_detail.htm?bizOrderId=45055548819742&his=false" target="_blank">详情</a>(rr2 =~ /<a href="(http:\/\/trade\.taobao\.com\/trade\/detail\/trade_item_detail\.htm[^"]+)" target="_blank">/).each{Map item = [:]item.url = it[1]member_ll << item}member_ll.each{String dd = get(httpclient, host, it.url)(dd =~ /收货地址:<\/th>[^<]+<td>([^<]+)<\/td>/).each{gg ->it.info = gg[1]}(dd =~ /<span class="nickname">([^<]+)<\/span>/).each{gg ->it.nick = gg[1]}}member_ll.each{def item = db.firstRow("select id from taobao_member_trade where info = ?", [it.info])if(item){println 'Skip trade for ' + it.nick}else{List args = [it.info, it.nick]db.executeUpdate("insert into taobao_member_trade(info, nick) values (?,?)", args)println 'Add trade ok for ' + it.nick}}}httpclient.getConnectionManager().shutdown()
?

?

读书人网 >互联网

热点推荐