更多>>关于我们

西安鲲之鹏网络信息技术有限公司从2010年开始专注于Web(网站)数据抓取领域。致力于为广大中国客户提供准确、快捷的数据采集相关服务。我们采用分布式系统架构,日采集网页数千万。我们拥有海量稳定高匿HTTP代理IP地址池,可以有效获取互联网任何公开可见信息。

您只需告诉我们您想抓取的网站是什么,您感兴趣的字段有哪些,你需要的数据是哪种格式,我们将为您做所有的工作,最后把数据(或程序)交付给你。

数据的格式可以是CSV、JSON、XML、ACCESS、SQLITE、MSSQL、MYSQL等等。

更多>>官方微博

西安鲲之鹏
陕西 西安

加关注

  • 【经验分享】如何让安卓设备(非模拟器)开机自动开启“网络ADB调试”(或叫做ADB over network/ADB over WIFI)?

    前面曾介绍过对于Bliss OS X86系统,可以通过修改/etc/init.sh文件,加入如下命令实现:
    setprop service.adb.tcp.port 5555
    stop adbd
    start adbd
    原理是adbd服务在启动的时候会先检查系统是否设置了service.adb.tcp.port属性,如果设置了就开启“网络ADB调试”。详见这篇文章:http://ytydyd.blog.sohu.com/146260552.html

    但对于真机设备的ROM,如何实现在开机的时候执行上述命令呢?

    以下方法均无效。
    (1)没有类似Bliss OS的/etc/init.sh文件。
    (2)stackoverflow上有人说可以通过在/etc/init.d/目录添加可执行脚本,试了也无效。
    (3)也有人说可以通过添加/data/local/userinit.sh脚本来实现(详见https://android.stackexchange.com/questions/6558/how-can-i-run-a-script-on-boot),试了也无效。

    最后在XDA论坛上看到一个叫做“Boot Shell”的App解决了问题。它能实现在设备系统启动之后执行事先添加好的命令或指定的脚本。
    (1)“Boot Shell”的详细介绍和下载地址见http://t.cn/A6LoSJdb,确保你的设备已经ROOT,否则无法使用。
    (2)安装后启动软件,点击左侧菜单“Add command”,输入一个名称,然后在Command栏填入要执行的命令:“setprop service.adb.tcp.port 5555;stop adbd;start adbd”。如图1所示。
    (3)重启设备,Boot Shell首次自启动,会提示ROOT授权,允许即可。
    试下"adb connect 手机ip:5555",不出意外的话就能直接连接了。
    需要注意的是,开发者选项里“网络ADB调试”此时状态可能依旧是未开启(如图2所示),但实际上我们已经通过后台命令启动了。
    发布时间:2020-06-20 16:46:38
  • 【经验分享】Ubuntu 下 Squid 基于 MySQL的用户认证配置步骤

    进行如下操作之前,确保已经正确安装和配置好了Squid和MySQL。
    (1)安装Perl的MySQL操作库libdbd-mysql-perl,后面Squid的认证脚本basic_db_auth中将会用到。
    sudo apt-get install libdbd-mysql-perl

    (2)在MySQL中创建Squid用户认证表,例如:
    CREATE TABLE `passwd` (
      `user` varchar(32) NOT NULL default '',
      `password` varchar(35) NOT NULL default '',
      `enabled` tinyint(1) NOT NULL default '1',
      `fullname` varchar(60) default NULL,
      `comment` varchar(60) default NULL,
      PRIMARY KEY  (`user`)
    );
    说明:Squid的代理认证协议是HTTP Basic Proxy Authentication。
      这里的`user` 为代理认证使用的用户名,  `password`为对应的密码, `enabled` 为1的账户才会被认为可用。

    (3)编辑/etc/squid/squid.conf,在http_access deny all之前加入:
    auth_param basic program /usr/lib/squid/basic_db_auth --dsn "DBI:mysql:host=MYSQL数据库IP;port=3306;database=MYSQL数据库名" --table passwd  --user MYSQL用户名 --password MYSQL密码 --plaintext --persist
    # 设置用户名和密码的缓存时间,减少数据库查询
    auth_param basic credentialsttl 2 hours

    保存并重启Squid。

    (4)配置完毕。通过对passwd表的增改删操作,就能实现对Squid代理用户的权限控制。

    参考:https://wiki.squid-cache.org/ConfigExamples/Authenticate/Mysql
    发布时间:2020-06-20 15:15:37
  • 【经验分享】接上篇“毒(得物)APP数据采集”。上篇提到了这个APP对HTTP请求做了"手脚"无法直接抓到包。这里分析一下,它到底做的什么"手脚",以及怎么绕过。

    1. 在com.shizhuang.duapp.common.helper.net.RestClient类中可要找到如下代码:
    writeTimeout.proxy(Proxy.NO_PROXY);(详见图1)
    这里 writeTimeout是一个OkHttpClient实例,OkHttpClient.proxy(Proxy.NO_PROXY),意思就是不使用(绕过)系统代理。
    绕过这个的方法有两个:
    (1) 让DuConfig.f277505a的值为true,这样就能避免执行“writeTimeout.proxy(Proxy.NO_PROXY);”,从而使用系统代理。
    而DuConfig.f277505a = applicationInfo.metaData.getBoolean("debug");(详见图2)
    因此我们可以通过Hook Bundle.getBoolean()让其返回true,另外一个思路是HookOkHttpClient.proxy,让其失效。
    (2)使用Proxifier让安卓模拟器进程的流量(例如夜神的NoxVMHandle.exe)强制转发给Fiddler。这种方法比较通用。

    2. 另外APP里还加了证书固定机制,通过代理后会报网络异常。
    通过如下代码可以绕过:
    var OkHostnameVerifier = Java.use('okhttp3.internal.tls.OkHostnameVerifier');
            OkHostnameVerifier.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(arg1, arg2){
               console.log("OkHostnameVerifier.verify('java.lang.String', 'java.security.cert.X509Certificate') called.");
               console.log(arg1);
               console.log(arg2);
               return true;    
            }
            
            OkHostnameVerifier.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(arg1, arg2){
                console.log("OkHostnameVerifier.verify('java.lang.String', 'javax.net.ssl.SSLSession') called.");
                console.log(arg1);
                console.log(arg2);
                return true;    
             }
             
             var CertificatePinner = Java.use('okhttp3.CertificatePinner');
             CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function (arg1, arg2) {
                 console.log('CertificatePinner.check() called. ');
                 console.log(arg1);
                 console.log(arg2);
             }
        
        var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
             OpenSSLSocketImpl.verifyCertificateChain.implementation = function (arg1, arg2) {
                 console.log('OpenSSLSocketImpl.verifyCertificateChain() called.');
                 console.log(arg1);
                 console.log(arg2);
            }
    PS:上述代码和之前我们发的“58同城APP证书固定机制绕过(ssl unpinning)方法”中的一样。

    经过上述两步之后,就能顺利抓到HTTP(s)流量,如图3所示。
    发布时间:2020-06-18 09:45:05
  • 【经验分享】毒(得物)APP签名算法解决

    (1)HTTP请求做了"手脚"无法直接抓到包。
    (2)分析代码后发现可以通过HOOK "com.shizhuang.duapp.common.helper.net.interceptor.HttpRequestInterceptor.intercept()"调用或者"okhttp3.internal.http.RealInterceptorChain.proceed()"调用拿到HTTP请求和应答数据(如图1所示)。
    (3)分析发现不关是GET请求,还是POST请求,都有一个签名参数newSign。签名算法位于com.shizhuang.duapp.common.utils.RequestUtils中,签名算法原理是对QueryString或Request Body中的参数以及一些特定的Headers排序后进行加密(具体加密算法是在native层实现的,位于libJNIEncrypt.so中),然后对加密结果进行MD5计算(如图2)。
    (4)分析出来原理后,思路就清晰了:自己构造HTTP请求,通过HOOK + RPC形式直接调用RequestUtils中的签名算法,产生有效的签名值,这样就能直接拿到接口返回的数据。如图3、4所示为最终采集到的数据。
    发布时间:2020-06-14 19:04:23
  • 【经验分享】58同城APP证书固定机制绕过(ssl unpinning)方法

    1. 直接抓包,APP提示网络错误(图1),logcat显示有okhtt3 connectTls相关函数异常(图2)。

    2.反编译APK,根据异常提示定位到证书锁定相关代码。

    3. 使用Frida Hook绕过相关证书验证代码。具体frida脚本如下:

    Java.perform(function() {
        
        console.log("##### com.wuba SSL UNPINNING #####");
        var OkHostnameVerifier = Java.use('okhttp3.internal.tls.OkHostnameVerifier');
        OkHostnameVerifier.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function(arg1, arg2){
           console.log("OkHostnameVerifier.verify('java.lang.String', 'java.security.cert.X509Certificate') called.");
           console.log(arg1);
           console.log(arg2);
           return true;    
        }
        
        OkHostnameVerifier.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function(arg1, arg2){
            console.log("OkHostnameVerifier.verify('java.lang.String', 'javax.net.ssl.SSLSession') called.");
            console.log(arg1);
            console.log(arg2);
            return true;    
         }
         
         var CertificatePinner = Java.use('okhttp3.CertificatePinner');
         CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function (arg1, arg2) {
             console.log('CertificatePinner.check() called. ');
             console.log(arg1);
             console.log(arg2);
         }

    var OpenSSLSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLSocketImpl');
         OpenSSLSocketImpl.verifyCertificateChain.implementation = function (arg1, arg2) {
             console.log('OpenSSLSocketImpl.verifyCertificateChain() called.');
             console.log(arg1);
             console.log(arg2);
        }
    }};
    '''
    4. 成功抓到相关HTTPS数据包(图3)。
    发布时间:2020-06-04 10:20:59
  • 【经验分享】VMware Workstation开机免登录自启动设置方法
    近日某拨号服务器出现故障,不定期会自动重启。每次重启之后都要手动去启动VMware虚拟机,非常麻烦。如何实现开机自启动指定的VMware虚拟机呢?

    (1)通过"vmrun.exe start 虚拟机vmx文件路径"命令可以启动指定的虚拟机。
    如果有多个虚拟机可以创建一个如下批处理:
    "C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe" start "E:\鲲之鹏\ubuntu16.04-adsl-proxies-server-1\Ubuntu 64 位.vmx"
    "C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe" start "E:\鲲之鹏\ubuntu16.04-adsl-proxies-server-2\Ubuntu 64 位.vmx"
    "C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe" start "E:\鲲之鹏\ubuntu16.04-adsl-proxies-server-3\Ubuntu 64 位.vmx"
    ...

    (2)将上述批处理文件添加到开机启动计划任务里。
    * 触发器,新建触发器,开启任务选择“启动时"。
    * 常规选项卡,安全选项选择“不管用户是否登录都要运行”。这一步很重要。

    为什么不直接放到“启动文件夹”中,而要使用计划任务呢?
    因为放到启动文件夹中必须要用户登录之后才能被执行。这样就达不到免登录自启动的效果了。
    发布时间:2020-05-26 17:33:42
  • 【经验分享】Pandas日期范围查询
    目的:查询CSV中某列值大于某个日期的记录。

    (1)使用Pandas的to_datetime()方法,将列类型从object转为datetime64。
    df[u'合同签订日期'] = pd.to_datetime(df[u'合同签订日期'], format=u'%Y年%m月%d日')
    注意要设置format参数,指定原始数据的时间日期格式。转换完成后可以查看dtypes属性确认,如附图1所示。参考:https://stackoverflow.com/questions/36848514/how-to-define-format-when-use-pandas-to-datetime
    (2)查询日期大于2018年1月1日的记录。
    df[df[u'合同签订日期'] >= pd.Timestamp(2018, 1, 1)]
    结果如附图2所示,参考:https://stackoverflow.com/questions/36104500/pandas-filtering-and-comparing-dates
    发布时间:2020-05-11 09:38:32
  • 【经验分享】Python的hash()函数产生hash碰撞的概率有这么高吗?

    昨天同事"随手"给我发了两组他在项目中遇到的例子,很是受"惊吓",HashDict用了快10年了,竟然没注意到这个Bug。

    Python 2.7.8.10 on Windows 64

    例一:
    hash(u'赤峰_1513781081_http://t.cn/A6Al6TDu)
    901186270
    hash(u'北京_1010215433_http://t.cn/A6Al6TDn)
    901186270

    例二:
    hash('B033900G0Z')
    80468932
    hash('B021307H9T')
    80468932

    注意: Linux 64 下测试上述两组值并不相同,另外Linux下hash()产生的hash串长度要比Windows下长很多,产生hash碰撞的概率应该也会小很多。
    发布时间:2020-05-08 21:05:47
  • 【经验分享】"土地市场网-土地供应-出让公告"网页字体混淆反采集的解决

    (1)如附图1所示,下载的页面中有很多字符是乱码。左边是经过浏览器正确渲染的结果,右边是下载到的有乱码的数据。
    (2)经过分析发现,网站使用了自定义的字体文件:把常用的391个汉字做成了特殊字体,使用了自定义的unicode码。如附图2所示。这种字体混淆的反采集策略现在很常见了,之前曾在猫眼电影、汽车之家、58等网站都见到过。
    (3)经过深入分析发现,网站总共使用了10个自定义的字体文件(如图3所示),每个文件内的字符是一样的(都是那391个字符),但是相同的unicode码对应的字符是不一样的。如附图4所示,uni3075在3个字体文件中对应的字符分别是“悬”、“亲”和“田”。
    (4)突破这种策略的思路很简单,就是建立一个“unicode码->字符"的映射表,然后将HTML中的这些乱码(unicode码)替换成明文即可。但是本例中有10 * 391 = 3910个字符,工作量太大了。
    (5)于是想到一个“偷懒”的方法:由于每个文件内都是那391个字符,我只手动建立一个映射表,其余的通过图片匹配自动建立。
    我把这个脚本放到了gist上“将字体文件内各字体导出图片存储,并建立一个Excel索引”(http://t.cn/A6wxdZxl)。
    如附图5所示,是上述脚本输出的每个字符对应的图片。
    如附图6所示,这个Excel文件也是上述脚本生成的,然后人工填入每个图片对应的明文字符,这样就建立好了一个字体文件的字符映射表。把这个表当做特征库表。
    (6)将其他9个字体文件中的图片也使用上述脚本导出,然后挨个和特征库对比(这里我直接通过像素值二维数组进行对比,将一致率最高的视为匹配),建立匹配关系,如图7所示。
    最终生成其它10张字符映射表,如附图8所示。
    (7)有了这10张完备的字体映射表,还原明文就so easy了,最终还原后的提取结果如附图9所示。
    发布时间:2020-04-15 10:53:11
  • 【经验分享】我查查APP防护机制分析

    1. 最明显的是URL加密了,如附图1所示。
    反编译后分析源码可知,URL加密过程如附图2所示。
    主要通过WccBarcode.getInstance().enReq(bytes, bytes.length)实现。

    2.  enReq()是一个native方法,具体实现在libgcbarcode_k.so中,如附图3所示。
    例如,原始URL:
    /ggstudy/price?city_id=1&pkid=46893149&token=eff213b02959eae34935f83ff1216a27&mac=6C%3A62%3A6D%3A27%3A4E%3A42&his=1586159685.1586183377&newudid=73288dee8365b5a2e088c6d91c4c95ad&ptoken=a94e255b4c4d444a9c66a324160bb63b&noscan=1&connectnet=wifi&lng=105.56721418292932&os=Android&v=9.3.0&originprice=4&device_model=HUAWEI+MLA-AL10&device_brand=HUAWEI&udid=863064017108624&lat=33.99952368518388
    经过加密后变成:
    /zzE06D4C3D909AE1E6261070A7B491241430713222ECA16B97C2005E0CB490484AB8713F03F811CB0A04522B2BAC2126961E31190DA820061096034A0BDC410713BC623924CC90A3C69A01182D1890......

    3. 上面有一个ptoken要特别注意,这其实是一个签名参数,具体的实现过程在com.wochacha.datacenter.es.d()方法中,如附图4所示。
    思路是先将querystring的key按从大到小排序,然后拼接成一个串,计算MD5后,再前后拼接上一个常量串(加盐),再次计算MD5。

    4. 另外,根据输入条码查询商品时,输入的barcode也被做了特殊处理。如图5所示。这里也调用了libgcbarcode_k.so中的native方法,conv()。

    了解上述过程后,我们就能自己过程出有效的HTTP请求,拿到数据。对于so中的算法,直接还原有难度,可以通过Frida RPC间接调用。最终效果如附图6所示。
    发布时间:2020-04-07 11:49:57
当前位置: 首页 > 技术文章 >
知名本地生活信息平台5303万POI数据2019年更新
发布时间:2020-02-07

数据说明

知名本地生活信息平台各品类商户数据,本次共采集到超过5303万条(53032367条,总数统计如下图所示)。 2019年6月-2020年1月采集。
PS:仅商户基本信息数据,不含评论列表数据。

知名本地生活信息平台5303万POI数据统计截图

 

更新说明

1.本轮共采集到了5303万条不重复的POI数据。PS:使用shop_id作为主键,没有重复。

2.本轮更新开始于2019年6月中旬,完成于2020年1月中旬,耗时近7个月。

3.数据涵盖美食、休闲娱乐、丽人、酒店、亲子、景点、运动健身、购物、家装、教育培训、生活服务、医疗健康、爱车、宠物、结婚等15大类。
各分类数据量如下:
美食 15408473
丽人 3465759
酒店 1080155  
亲子 1357050
景点 250719
运动健身 300395
购物 10171669
家装 5077941
教育培训 1535670
生活服务 6691821
休闲娱乐 1750485
医疗健康 1760787
宠物 154696
爱车 2965910
结婚 755022
其它 305815

4. 数据覆盖全国约400个城市,不含境外城市。

5. 本次采集首先对2018年6月份的采集版本(4794万)做了全量完整更新。同时通过遍历POI列表又新采集到509万新增的POI。

6. 本版本5303万商户POI数据中:
■状态为"在营业"的有34076224条;
■状态为"关闭"的有18512495条;
■状态为"尚未营业"的有151144条;
■状态为"暂停营业"的有284907条;
■状态为"网友提交"的公共信息7597条。
PS:关闭的店铺在源网站上仍将可以打开,页面会有标志"商户已关"。

7. 其中有电话号码的28634002家(约占总数据量的54%)。

8. 本次采集的是APP数据源,2018年6月之前均采集的是PC版数据源。因此字段有所调整,例如少了"good_remarks"(好评数)和"bad_remarks"(差评数)字段。

 

字段说明

1. "shop_id"(商户ID,唯一、固定不变)
2. "status"(商户状态:0 - 正常营业;1 - 已关店;2 - 商户尚未营业;3 - 暂停营业;4 - 网友提交的公共信息。)
3. "name" (商户名称)
4. "city_id" (城市ID)
5. "city"(站点城市名称)
6. "real_city"(真实归属城市,点击查看城市列表
7. "province"(省份)
8. "avg_price"(均价)
9. "area_code"(电话区号)
10. "phone"(联系电话)
11. "regionname"(所属区县或商圈)
12. "address"(地址)
13. "cross_road"(所在交叉路口)
14. "big_category_id"(一级大类ID)
15. "big_category"(一级大类名称,点击查看分类列表
16. "small_category"(二级分类名称,点击查看分类列表
17. "star"(评分)
18. "longitude"(经度,腾讯地图)
19. "latitude"(纬度,腾讯地图)
20. "score1"(口味/产品评分)
21. "score2"(环境评分)
22. "score3"(服务评分)
23. "score4"(其它评分)
24. "review_count"(评论总数)
25. "bookable"(是否接受预定)
26. "default_pic"(店铺默认图片)
27. "alt_name"(商户别名)
28. "branchname"(分店名)
29. "dishtags"(推荐菜)
30. "updated"(数据采集时间)
31. "url"(源URL)

 

数据格式

数据格式:CSV和MySQL。

字符编码:UTF-8。

文件大小:RAR压缩后3.41GB,解压后约20GB。

 

示例数据

点击查看:http://db.site-digger.com/csv/6469616e70696e675f73686f70735f3230313930362d3230323030325f76335f757466385f73616d706c655f31303030/
温馨提示:为了保护个人隐私,示例数据中的手机号码隐藏了中间4位。

特别说明:本文旨在技术交流,请勿将涉及的技术用于非法用途,否则一切后果自负。如果您觉得我们侵犯了您的合法权益,请联系我们予以处理。
☹ Disqus被Qiang了,之前所有的评论内容都看不到了。如果您有爬虫相关技术方面的问题,欢迎发到我们的问答平台:http://spider.site-digger.com/
QQ在线客服
欢迎咨询,点击这里给我发送消息。
欢迎咨询,点击这里给我发送消息。

加微信咨询