HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

关于Mac版Hbuilder X文件查找失败的bug的【解决方案】

问题描述

Mac版Hbuilder X创建uni-app项目后,运行时会提示“文件查找失败,找不到xxxx/main.js”。

解决方案:

1.将新创建的项目【从项目列表移除】
2.选择【文件-打开目录】重新打开之前创建的项目

此时就可以运行成功。

另外如果提示“尚不支持此种类型文件”,在排除真的是类型原因的情况下,按以上方式操作也能解决该问题。

具体是不是bug,目前还不清楚,这个问题困扰了好久,网上也找不到答案,所以写出来,分享给有同样问题的小伙伴。

继续阅读 »

问题描述

Mac版Hbuilder X创建uni-app项目后,运行时会提示“文件查找失败,找不到xxxx/main.js”。

解决方案:

1.将新创建的项目【从项目列表移除】
2.选择【文件-打开目录】重新打开之前创建的项目

此时就可以运行成功。

另外如果提示“尚不支持此种类型文件”,在排除真的是类型原因的情况下,按以上方式操作也能解决该问题。

具体是不是bug,目前还不清楚,这个问题困扰了好久,网上也找不到答案,所以写出来,分享给有同样问题的小伙伴。

收起阅读 »

iOS马甲包上架方法论

iOS 外包 招聘

> 马甲包是利用各大市场规则漏洞,通过技术手段,多次上架同一款产品的方法。马甲包和主产品包拥有同样的内容和功能,除了icon和应用名称不能完全一致,其他基本一致。
至于为什么做马甲包,能读这篇文章的自然也不需要我多说什么了吧,引流、抗风险、关键词覆盖、刷榜,对于一些灰色产业或者用户获取竞争激烈的行业领域来说,意义非凡。但是苹果爸爸可不允许这种情况发生,马甲包在审核环节,是非常容易被拒的,毕竟破坏苹果商店公平性的东西,是不被允许的。

当然,我们对iOS的审核机制进行了深入的研究和尝试,马甲包也是成功上架过很多了。马甲包该如何上架呢?找我就好啦~ 哈哈哈!!言归正传,下文详述。

那么马甲包该如何上架?

需要马甲包代上架的可以联系我,QQ:1481983952

马甲包被拒最常见的4.3被拒

  1. 3 Design: SpamGuideline 4.3 - Design

首先4.3基本是机器审,是你之前用这套源码上过一个包,现在用这套代码直接改一个logo跟名字再上一个马甲,这种基本会直接4.3

这种情况基本要改源码,First:文件夹的名字全部进行修改。Second:工程都有一个class前缀, 我们要取一个长一点的class前缀, 并且这个类前缀在你的整个工程一定是一个唯一的字符串, 我们假设这个类前缀是iosMaJiaBao, 现在我们需要生成一个控制器, 控制器的结尾Controller也需要用一个特定的字符去代替, 比如:Director,剩下的View以及object做法类似, 就不一一介绍了,做马甲的时候就是把这些名字用另一个唯一的字符去代替, 尽量长一点。Third:把另一个其他的工程中的类全部导入进来, 作用是混淆代码, 在现有的工程中调用, 可以没有任何效果, 只是单纯相互调用而已~~~

别想着单一加垃圾代码,没用的!!!

其实还有很多别的情况,下次再一一解释并给出解决方案吧,今天有点懒了呢~

继续阅读 »

> 马甲包是利用各大市场规则漏洞,通过技术手段,多次上架同一款产品的方法。马甲包和主产品包拥有同样的内容和功能,除了icon和应用名称不能完全一致,其他基本一致。
至于为什么做马甲包,能读这篇文章的自然也不需要我多说什么了吧,引流、抗风险、关键词覆盖、刷榜,对于一些灰色产业或者用户获取竞争激烈的行业领域来说,意义非凡。但是苹果爸爸可不允许这种情况发生,马甲包在审核环节,是非常容易被拒的,毕竟破坏苹果商店公平性的东西,是不被允许的。

当然,我们对iOS的审核机制进行了深入的研究和尝试,马甲包也是成功上架过很多了。马甲包该如何上架呢?找我就好啦~ 哈哈哈!!言归正传,下文详述。

那么马甲包该如何上架?

需要马甲包代上架的可以联系我,QQ:1481983952

马甲包被拒最常见的4.3被拒

  1. 3 Design: SpamGuideline 4.3 - Design

首先4.3基本是机器审,是你之前用这套源码上过一个包,现在用这套代码直接改一个logo跟名字再上一个马甲,这种基本会直接4.3

这种情况基本要改源码,First:文件夹的名字全部进行修改。Second:工程都有一个class前缀, 我们要取一个长一点的class前缀, 并且这个类前缀在你的整个工程一定是一个唯一的字符串, 我们假设这个类前缀是iosMaJiaBao, 现在我们需要生成一个控制器, 控制器的结尾Controller也需要用一个特定的字符去代替, 比如:Director,剩下的View以及object做法类似, 就不一一介绍了,做马甲的时候就是把这些名字用另一个唯一的字符去代替, 尽量长一点。Third:把另一个其他的工程中的类全部导入进来, 作用是混淆代码, 在现有的工程中调用, 可以没有任何效果, 只是单纯相互调用而已~~~

别想着单一加垃圾代码,没用的!!!

其实还有很多别的情况,下次再一一解释并给出解决方案吧,今天有点懒了呢~

收起阅读 »

uniapp向webview中发送消息

uniapp

uniapp向webview中发送消息

在业务开发中,使用webview嵌套了vue开发的h5页面,进行套壳打包,其一需求是,在h5中获取当前app的版本号,就涉及到了uniapp向webview传递消息的场景

uniapp 中代码

核心为获取到webview窗口,然后通过evalJS执行h5中的方法

  • setVersion方法为h5页面中定义的全局方法
<template>  
    <view class="content">  
        <!-- 开发 -->  
        <web-view @message="onMessage" :webview-styles="webviewStyles" src="http://192.168.1.158:3000"></web-view>  

    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            title: 'Hello',  
            webviewStyles: {  
                progress: {  
                    color: '#f0b90b'  
                }  
            },  
            wv: null,  
        };  
    },  
    onLoad() {  
        const self = this;  
        // #ifdef APP-PLUS  
        let currentWebview = this.$scope.$getAppWebview();  
        setTimeout(function() {  
            let wv = currentWebview.children()[0];  
            self.wv = wv;  
            self.setVersion();  
        }, 1000);  
        // #endif  

    },  
    methods: {  
        // 设置版本号  
        setVersion() {  
            const self = this;  
            plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {  
                self.wv.evalJS("setVersion('" + widgetInfo.version + "')");  
            });  
        },  
        // 接收消息  
        onMessage(e) {  
            const self = this;  
            console.log('我收到了网页发来的消息', e.detail.data);  
            let data = e.detail.data;  
        },  
    }  
};  
</script>  

h5 中代码

App.vue

// 设置版本号  
    window.setVersion = (id) => {  
      localStorage.setItem("version", version);  
    };

然后就可以在h5中获取使用了

注意

尽量不要uni生命周期中直接调用h5里面的方法,要等h5加载完成后,才可以调用

继续阅读 »

uniapp向webview中发送消息

在业务开发中,使用webview嵌套了vue开发的h5页面,进行套壳打包,其一需求是,在h5中获取当前app的版本号,就涉及到了uniapp向webview传递消息的场景

uniapp 中代码

核心为获取到webview窗口,然后通过evalJS执行h5中的方法

  • setVersion方法为h5页面中定义的全局方法
<template>  
    <view class="content">  
        <!-- 开发 -->  
        <web-view @message="onMessage" :webview-styles="webviewStyles" src="http://192.168.1.158:3000"></web-view>  

    </view>  
</template>  
<script>  
export default {  
    data() {  
        return {  
            title: 'Hello',  
            webviewStyles: {  
                progress: {  
                    color: '#f0b90b'  
                }  
            },  
            wv: null,  
        };  
    },  
    onLoad() {  
        const self = this;  
        // #ifdef APP-PLUS  
        let currentWebview = this.$scope.$getAppWebview();  
        setTimeout(function() {  
            let wv = currentWebview.children()[0];  
            self.wv = wv;  
            self.setVersion();  
        }, 1000);  
        // #endif  

    },  
    methods: {  
        // 设置版本号  
        setVersion() {  
            const self = this;  
            plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {  
                self.wv.evalJS("setVersion('" + widgetInfo.version + "')");  
            });  
        },  
        // 接收消息  
        onMessage(e) {  
            const self = this;  
            console.log('我收到了网页发来的消息', e.detail.data);  
            let data = e.detail.data;  
        },  
    }  
};  
</script>  

h5 中代码

App.vue

// 设置版本号  
    window.setVersion = (id) => {  
      localStorage.setItem("version", version);  
    };

然后就可以在h5中获取使用了

注意

尽量不要uni生命周期中直接调用h5里面的方法,要等h5加载完成后,才可以调用

收起阅读 »

uniapp原生插件-监听手机短信

原生插件

监听手机短信

实时监控手机收到的短信,可获取到发送者的手机号、时间、内容、卡槽等相关信息

使用方法

  • 下载本插件并存放到nativeplugins目录下

  • 在页面中引入这个插件

    // 监听短信插件  
    const kingReceiceSmsModule = uni.requireNativePlugin("king-receive-sms")  
  • 调用插件的方法

    kingReceiceSmsModule.addCustomizeNotifyMessage(result => {  
        <!-- result 为监听到的信息 -->  
        var str = JSON.stringify(result);  
        console.log(str)  
    });  

    信息格式

    {  
    "timestamp":1611751876000,  
    "originatingAddress":"+86666666",  
    "body":"我是信息内容",  
    "subId":0  
    }
  • timestamp 接收的时间

  • originatingAddress 发送者的号码

  • body 信息内容

  • subId 卡槽下标

注意事项

  • 使用前,请确认已经开通 短信读取权限接收新短信权限
  • 如果没有开通,请引导用户进行授权,可建议使用这个插件 App权限判断和提示,进行判断开启

java 核心源代码

package io.king.uniplugin;  

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.os.Build;  
import android.os.Bundle;  
import android.provider.Telephony;  
import android.telephony.SmsMessage;  
import android.util.Log;  

import java.lang.reflect.Method;  
import java.util.HashMap;  
import java.util.Map;  

public class SmsReceiver extends BroadcastReceiver {  

    public static final String TAG = "SmsListenerPackage";  
    public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";  

    private void receiveMessages(SmsMessage[] messages) throws Exception {  
        if (messages == null) {  
            return;  
        }  

        Class ownerClass = Class.forName("android.telephony.SmsMessage");  
        Method method = ownerClass.getMethod("getSubId");  

        Map<String, String> msg = new HashMap<String, String>(messages.length);  
        Map<String, Integer> msgSubId = new HashMap<String, Integer>(messages.length);  
        Map<String, Long> msgTime = new HashMap<String, Long>(messages.length);  
        for (SmsMessage message : messages) {  
            String originatingAddress = message.getOriginatingAddress();  

            // Check if index with number exists  
            if (!msg.containsKey(originatingAddress)) {  
                msg.put(originatingAddress, message.getMessageBody());  
                int subId = (int) method.invoke(message);  
                msgSubId.put(originatingAddress, subId);  
                msgTime.put(originatingAddress, message.getTimestampMillis());  
            } else {  
                String previousParts = msg.get(originatingAddress);  
                String msgString = previousParts + message.getMessageBody();  
                msg.put(originatingAddress, msgString);  
            }  
        }  

        for (String sender : msg.keySet()) {  
            Log.d(  
                    TAG,  
                    String.format("%s: %s", sender, msg.get(sender))  
            );  

            Map<String, Object> receivedMessage = new HashMap<>();  

            receivedMessage.put("originatingAddress", sender);  
            receivedMessage.put("body", msg.get(sender));  
            receivedMessage.put("timestamp", msgTime.get(sender));  
            receivedMessage.put("subId", msgSubId.get(sender));  

            if (CallBack.getInstance().customizeNotifyMessage != null) {  
                CallBack.getInstance().customizeNotifyMessage.onCustomizeNotifyMessage(receivedMessage);  
            }  
        }  
    }  

    @Override  
    public void onReceive(Context context, Intent intent) {  
        SmsMessage[] messages = null;  

        if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {  
            try {  
                final Bundle bundle = intent.getExtras();  

                if (bundle == null || !bundle.containsKey("pdus")) {  
                    return;  
                }  

                final Object[] pdus = (Object[]) bundle.get("pdus");  
                messages = new SmsMessage[pdus.length];  

                for (int i = 0; i < pdus.length; i++) {  
                    byte[] pdu = (byte[]) pdus[i];  
                    messages[i] = SmsMessage.createFromPdu(pdu);  
                    Log.e(TAG,  messages[i].getMessageBody());  
                }  

            } catch (Exception e) {  
                Log.e(TAG, e.getMessage());  
            }  
        }  

        try {  
            receiveMessages(messages);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}
继续阅读 »

监听手机短信

实时监控手机收到的短信,可获取到发送者的手机号、时间、内容、卡槽等相关信息

使用方法

  • 下载本插件并存放到nativeplugins目录下

  • 在页面中引入这个插件

    // 监听短信插件  
    const kingReceiceSmsModule = uni.requireNativePlugin("king-receive-sms")  
  • 调用插件的方法

    kingReceiceSmsModule.addCustomizeNotifyMessage(result => {  
        <!-- result 为监听到的信息 -->  
        var str = JSON.stringify(result);  
        console.log(str)  
    });  

    信息格式

    {  
    "timestamp":1611751876000,  
    "originatingAddress":"+86666666",  
    "body":"我是信息内容",  
    "subId":0  
    }
  • timestamp 接收的时间

  • originatingAddress 发送者的号码

  • body 信息内容

  • subId 卡槽下标

注意事项

  • 使用前,请确认已经开通 短信读取权限接收新短信权限
  • 如果没有开通,请引导用户进行授权,可建议使用这个插件 App权限判断和提示,进行判断开启

java 核心源代码

package io.king.uniplugin;  

import android.content.BroadcastReceiver;  
import android.content.Context;  
import android.content.Intent;  
import android.os.Build;  
import android.os.Bundle;  
import android.provider.Telephony;  
import android.telephony.SmsMessage;  
import android.util.Log;  

import java.lang.reflect.Method;  
import java.util.HashMap;  
import java.util.Map;  

public class SmsReceiver extends BroadcastReceiver {  

    public static final String TAG = "SmsListenerPackage";  
    public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";  

    private void receiveMessages(SmsMessage[] messages) throws Exception {  
        if (messages == null) {  
            return;  
        }  

        Class ownerClass = Class.forName("android.telephony.SmsMessage");  
        Method method = ownerClass.getMethod("getSubId");  

        Map<String, String> msg = new HashMap<String, String>(messages.length);  
        Map<String, Integer> msgSubId = new HashMap<String, Integer>(messages.length);  
        Map<String, Long> msgTime = new HashMap<String, Long>(messages.length);  
        for (SmsMessage message : messages) {  
            String originatingAddress = message.getOriginatingAddress();  

            // Check if index with number exists  
            if (!msg.containsKey(originatingAddress)) {  
                msg.put(originatingAddress, message.getMessageBody());  
                int subId = (int) method.invoke(message);  
                msgSubId.put(originatingAddress, subId);  
                msgTime.put(originatingAddress, message.getTimestampMillis());  
            } else {  
                String previousParts = msg.get(originatingAddress);  
                String msgString = previousParts + message.getMessageBody();  
                msg.put(originatingAddress, msgString);  
            }  
        }  

        for (String sender : msg.keySet()) {  
            Log.d(  
                    TAG,  
                    String.format("%s: %s", sender, msg.get(sender))  
            );  

            Map<String, Object> receivedMessage = new HashMap<>();  

            receivedMessage.put("originatingAddress", sender);  
            receivedMessage.put("body", msg.get(sender));  
            receivedMessage.put("timestamp", msgTime.get(sender));  
            receivedMessage.put("subId", msgSubId.get(sender));  

            if (CallBack.getInstance().customizeNotifyMessage != null) {  
                CallBack.getInstance().customizeNotifyMessage.onCustomizeNotifyMessage(receivedMessage);  
            }  
        }  
    }  

    @Override  
    public void onReceive(Context context, Intent intent) {  
        SmsMessage[] messages = null;  

        if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {  
            try {  
                final Bundle bundle = intent.getExtras();  

                if (bundle == null || !bundle.containsKey("pdus")) {  
                    return;  
                }  

                final Object[] pdus = (Object[]) bundle.get("pdus");  
                messages = new SmsMessage[pdus.length];  

                for (int i = 0; i < pdus.length; i++) {  
                    byte[] pdu = (byte[]) pdus[i];  
                    messages[i] = SmsMessage.createFromPdu(pdu);  
                    Log.e(TAG,  messages[i].getMessageBody());  
                }  

            } catch (Exception e) {  
                Log.e(TAG, e.getMessage());  
            }  
        }  

        try {  
            receiveMessages(messages);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}
收起阅读 »

提供兼职实习岗位(前端)

此贴发布于2021年1月27日
有效期10天
到2021年2月7号后失效

本人运营了一个电商类型的网站.目前有4个项目

  • 移动端 uni-app + ts
  • pc端 vue3.x + ts
  • 管理后台1 uni-cloud-admin + ts + uni-clound-db
  • 管理后台2 react + ts + 原生uni-cloud

目前全部是自己开发.由于还在上班.精力不够.找1到2个学生或者初级前端一起开发

每个月1000到1500的补贴
更重要的是
带着你一起熟悉正规互联网公司的开发流程

要求
有一定的前端开发基础
好学
吃苦

需要回答以下几个问题
js和vue的区别
uni-app和vue的区别
uni-cloud和restfull的区别
你的前端职业规划
如果你没用过ts,你计划怎么学习

有意者加微信ranwawag

继续阅读 »

此贴发布于2021年1月27日
有效期10天
到2021年2月7号后失效

本人运营了一个电商类型的网站.目前有4个项目

  • 移动端 uni-app + ts
  • pc端 vue3.x + ts
  • 管理后台1 uni-cloud-admin + ts + uni-clound-db
  • 管理后台2 react + ts + 原生uni-cloud

目前全部是自己开发.由于还在上班.精力不够.找1到2个学生或者初级前端一起开发

每个月1000到1500的补贴
更重要的是
带着你一起熟悉正规互联网公司的开发流程

要求
有一定的前端开发基础
好学
吃苦

需要回答以下几个问题
js和vue的区别
uni-app和vue的区别
uni-cloud和restfull的区别
你的前端职业规划
如果你没用过ts,你计划怎么学习

有意者加微信ranwawag

收起阅读 »

最近程序员频繁被抓,如何避免面向监狱编程?

法律科普

最近,有很多关于程序员被抓甚至被判刑的新闻在朋友圈疯传:
"某程序员因为接了个外包,帮别人写了个软件,结果这个软件被用于赌博导致被抓。
某公司利用爬虫抓取用户信息,最后被发现,导致该公司的程序员被抓。
某P2P公司暴雷,老板跑路,程序员被抓。
中科大博士卖“外挂”非法牟利300多万,被警方逮捕。"

那么,作为一个程序员,如何避免这些坑呢?怎样尽可能的保护自己呢?
为此,作者特地找自己法律专业的朋友了解了一些常见的问题,如参与爬虫、赌博网站、P2P以及外挂开发是否违法等问题。

总结出了这篇文章,一起探讨一下"技术到底是不是真的无罪?",作为程序员如何避免面向监狱编程!
由于作者并非专业的法律工作从业者,文中法规部分的引用如有偏差,请指正。希望通过本文可以帮助广大程序员们了解一下有哪些自己的人身自由息息相关的坑。

一、爬虫

爬虫,是互联网时代一项普遍运用的网络信息搜集技术。该项技术最早应用于搜索引擎领域,是搜索引擎获取数据来源的支撑性技术之一。

随着数据资源的爆炸式增长,网络爬虫的应用场景和商业模式变得更加广泛和多样,较为常见的有新闻平台的内容汇聚和生成、电子商务平台的价格对比功能、基于气象数据的天气预报应用等等。

网络爬虫技术为数据收集者提供了极大的便利,也给专业网络爬虫公司带来巨大的收益。所以,很多公司都会有爬虫部门,或者负责开发爬虫的团队,在招聘网站上,也随处可见关于"爬虫工程师"的招聘贴。

关于这个问题,一直都是比较难定性的,因为爬虫本身只是个工具,就和菜刀一样,所以很多人都拿"菜刀无罪论"、"技术无罪论"来为爬虫辩护。

从网络爬虫的相关案例来看,爬虫的开发及使用者通常有很多理由为自己辩护:

“我爬取的都是这个网站的公开数据,搜索引擎不也是这么做的吗?”

“这与搜索引擎行为类似,只是使用了自动脚本,这是合理使用行为。”

“我已经遵守了它们的robots协议、该网站没有robots协议”

“这些数据我只是个人研究使用,并没有商业目的”。

那么,爬虫到底犯不犯法?

目前,关于网络爬虫相关的约束,主要是2019年05月28日国家网信办发布的《数据安全管理办法(征求意见稿)》。这份文件主要包含了数据收集、数据处理使用以及数据安全监督管理三个章节。

基本可以确定的是,如果爬虫使用不当,那么爬虫的开发者是有可能触犯法律的,而根据情况不同,获得的刑罚也有可能有差异。

要看开发和使用爬虫是否犯法,需要从爬什么数据、如何爬取数据以及爬到数据之后怎么用三个方面来判断。接下来就简单分析一下:

爬什么数据犯法?

1、属于著作权法保护的作品

有些网站发表的内容,如文章、评论等都是有著作权的,如果只是单纯的通过浏览器查看是不会触犯法律的。

但是,对于有著作权的作品,如果未经著作权人许可,以盈利为目的,对其作品进行复制是会触犯法律的。

根据《中华人民共和国著作权法》第46条:有下列侵权行为的,应当根据情况,承担停止侵害、消除影响、公开赔礼道歉、赔偿损失等民事责任,并可以由著作权行政管理部门给予没收非法所得、罚款等行政处罚:(一)剽窃、抄袭他人作品的;(二)未经著作权人许可,以营利为目的,复制发行其作品的;(三)出版他人享有专有出版权的图书的;(四)未经表演者许可,对其表演制作录音录像出版的;(五)未经录音录像制作者许可,复制发行其制作的录音录像的;(六)未经广播电台、电视台许可,复制发行其制作的广播、电视节目的;(七)制作、出售假冒他人署名的美术作品的。

如果是使用爬虫技术手段爬取数据之后将其保存下来或者传播,并且进行盈利,这种都是属于犯罪的。

2、用户的个人信息或者个人隐私

个人用户的个人信息,即使是用户自己放到一些网站上进行公开或者部分公开,如微博、微信等,不代表这些数据就可以被其他人随便获取!

根据《民法总则》第111条:任何组织和个人需要获取他人个人信息的,应当依法取得并确保信息安全。不得非法收集、使用、加工、传输他人个人信息;
根据《网络安全法》第44条:任何个人和组织不得窃取或者以其他非法方式获取个人信息。因此,如果爬虫在未经用户同意的情况下大量抓取用户的个人信息,则有可能构成非法收集个人信息的违法行为。

所以,如果爬取的数据涉及到个人信息,都是违法的!

还有些爬虫企图绕过权限校验等,爬取用户未公开的信息,如个人私密相册照片等,都是属于侵犯用户的个人隐私的,这种也是违法的。

3、反不正当竞争保护的数据

目前有很多网站中的数据系由用户生成,且该等数据和内容系原告网站的主要竞争力来源。如大众点评上面的店铺评价、评论等信息,携程网上面的关于酒店的评价评论等信息等。

根据《反不正当竞争法》第2条:经营者在市场交易中,应当遵循自愿、平等、公平、诚实信用的原则,遵守公认的商业道德。

那么,未经允许,爬取其他网站的核心数据,很明显并没有遵守《反不正当竞争法》中规定的自愿、平等、公平、诚实信用的原则。
在大众点评诉百度不正当竞争案件、以及新浪微博诉脉脉不正当竞争等案件中,法院都认定被告未经许可抓取、使用原告网站中的数据的行为,违反了诚实信用原则及公认的道德,损害了互联网的市场竞争秩序,损害了原告的竞争优势,从而构成不正当竞争。

因此,如果抓取大众点评、微博、豆瓣电影、知乎等UGC模式的网站上用户发布的信息,并在自己的产品或者服务中发布、使用该等信息,则有较大的风险构成不正当竞争。

怎么爬犯法?

如果是爬取公开的数据,通常不会被认为是侵权。Google、百度等搜索引擎都是这么爬取的。

那么,到底怎么爬数据是有可能触犯法律的呢,主要考虑是否涉及以下两种行为:

未遵守Robots协议

Robots协议是技术界为了解决爬取方和被爬取方之间通过计算机程序完成关于爬取的意愿沟通而产生的一种机制。

根据《互联网搜索引擎服务自律公约》第7条:机器人协议(robots协议)是指互联网站所有者使用robots.txt文件,向网络机器人(Web robots)给出网站指令的协议。具体而言,robots协议是网站所有者通过位于置于网站根目录下的文本文件robots.txt,提示网络机器人哪些网页不应被抓取,哪些网页可以抓取。

根据《互联网搜索引擎服务自律公约》第8条:互联网站所有者设置机器人协议应遵循公平、开放和促进信息自由流动的原则,限制搜索引擎抓取应有行业公认合理的正当理由,不利用机器人协议进行不正当竞争行为,积极营造鼓励创新、公平公正的良性竞争环境。

虽然《互联网搜索引擎服务自律公约》仅适用于中国互联网协会会员单位和自愿加入《中国互联网行业自律公约》的互联网从业单位,但在司法实践中,Robots协议已经被认定构成互联网行业搜索领域内的商业道德。

因此,无视网站设置的Robots协议而随意抓取网站内容的行为将涉嫌构成对《反不正当竞争法》的第2条的违反,即违反诚实信用原则和商业道德的不正当竞争行为。

绕过防护措施对数据的访问,强行突破反爬措施

由于爬虫的批量访问会给网站带来巨大的压力和负担,因此许多网站经营者会采取技术手段,以阻止爬虫批量获取自己网站信息。

所以,很多爬虫工具为了爬取数据,会想办法通过各种手段绕过防护措施,但是,这种行为也是会触犯法律的。

根据《刑法》第285条第二款:违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。

企图通过技术手段,绕过网站的反爬机制,都属于《刑法》中规定的"侵入",都是要被处罚的。

怎么用犯法?

很多公司开发的爬虫遵守了Robots协议,也没有爬取不该爬取的数据,难道这样获取到的数据就可以随便使用了吗?其实也不是,如果使用不当,也会触犯法律的。

比如通过爬虫抓取到的数据进行盈利、损害他人利益、造假、诽谤等都是可能触犯法律的。

此外,未经被收集者同意,即使是将合法收集的公民个人信息向他人提供的,也属于刑法第二百五十三条之一规定的“提供公民个人信息”,可能构成犯罪。

小结

在使用爬虫的过程中,爬取的数据类型、爬取数据的方式以及爬取之后的使用都是可能触犯法律的。

其中,使用爬虫得到的数据进行盈利、损害他人利益、不正当竞争等一般都是针对经营者的。

但是对于程序员来说,如果你的老板让你开发的爬虫,是用来爬取用户的个人信息或者个人隐私,并且该爬虫未遵循Robots协议、或者有意的躲避反爬机制就可能触犯到法律了。

二、赌博、S情网站

除了爬虫以外,最近很多关于程序员参与赌博网站的开发,最终被判刑的新闻,那么,如果参与赌博、S情等网站的开发,是不是一定触犯法律呢?
这种情况主要看开发者是不是属于"明知故犯"。

根据《最高人民法院、最高人民检察院、公安部关于办理网络赌博犯罪案件适用法律若干问题的意见》中关于网上开设赌场共同犯罪的认定和处罚规定:

明知是赌博网站,而为其提供下列服务或者帮助的,属于开设赌场罪的共同犯罪,依照刑法第三百零三条第二款的规定处罚:

(一)为赌博网站提供互联网接入、服务器托管、网络存储空间、通讯传输通道、投放广告、发展会员、软件开发、技术支持等服务,收取服务费数额在2万元以上的;

(二)为赌博网站提供资金支付结算服务,收取服务费数额在1万元以上或者帮助收取赌资20万元以上的;

(三)为10个以上赌博网站投放与网址、赔率等信息有关的广告或者为赌博网站投放广告累计100条以上的。

也就是说,如果你作为程序员,你在帮公司开发赌博网站,只要公司付给你的费用超过了2万元以上,那么你就和开设赌场的人是共同犯罪。

除了赌博网站,所有和黄赌毒有关的软件开发都不要参与,明知道是违法或者可能违法的行为,并为其提供技术支持,都是有可能触犯法律的。快播不就是个很好的例子吗。
所以,程序员一定要远离赌博、色情等网站,并拒绝为他们提供技术服务。

三、P2P

最近,P2P频繁暴雷,因为是网络借贷,所以这些暴雷的公司必然是有程序员的,所以,对于这种P2P公司如果涉及违法,那么参与开发的程序员到底算不算从犯?

前段时间,有脉脉用户发帖称"P2P公司暴雷,前端程序员被抓":

一时间,引起了广泛的讨论,有人认为程序员为违法提供了帮助,属于从犯,有人认为程序员可能不知道公司违法,是"不知者不罪"

那么,关于这个情况,知乎上有用户给过专业的解答:

『如果程序员只是单纯的负责开发,只拿合理的死工资,本人对于公司的合法性和P2P的政策不了解,找工作也是通过正规渠道的。』那么就不算从犯。

但是,如果还负责了公司的其他事情,或者没有只拿死工资,找工作也不是正规渠道的,那就另当别论了。重要的是,如果自己明知道公司是非法的,那么肯定就涉及犯罪了。

所以,对于这种做互联网金融的企业的程序员,需要多多了解一下自己公司当前的主营业务是否合法。是否涉及到非法集资、传销等违法行为。

四、外挂

外挂是指利用电脑技术针对一个或多个网络游戏,通过改变软件的部分程序制作而成的作弊程序。制作贩卖游戏外挂也是会受到我国司法机关打击的行为。

根据开发者制作的不同的外挂类型,以及使用方式等,根据以往案例,可能触犯非法经营罪、破坏计算机信息系统罪以及侵犯著作权罪等。

非法经营罪

外挂等违法行为的出现,严重侵害了游戏开发者、运营商以及正常消费者的合法权益,扰乱了互联网游戏经营的正常秩序,破坏了网络游戏产业的良性发展,违反国家规定,情节严重,应按刑法第225条第四项的规定处罚。

根据《刑法》第225条:违反国家规定,有下列非法经营行为之一,扰乱市场秩序,情节严重的,处五年以下有期徒刑或者拘役,并处或者单处违法所得一倍以上五倍以下罚金;情节特别严重的,处五年以上有期徒刑,并处违法所得一倍以上五倍以下罚金或者没收财产:

一)未经许可经营法律、行政法规规定的专营、专卖物品或者其他限制买卖的物品的;

二)买卖进出口许可证、进出口原产地证明以及其他法律、行政法规规定的经营许可证或者批准文件的;

三)未经国家有关主管部门批准非法经营证券、期货、保险业务的,或者非法从事资金支付结算业务的;

四)其他严重扰乱市场秩序的非法经营行为。

破坏计算机信息系统罪

有些外挂会修改网络游戏运行数据、干扰网络游戏服务端计算机信息系统功能、危害计算机信息系统安全的行为,符合破坏计算机信息系统罪的犯罪构成要件。

根据《刑法》第286条:违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。

侵犯著作权罪

还有些开发者通过非法手段,获取他人享有著作权的计算机软件中的核心程序文件,制作外挂后用以牟利。这种外挂程序虽然与官方客户端程序并不完全一致,但主体结构、功能构成实质性相同,故被告人的行为构成非法复制计算机软件的行为,应以侵犯著作权罪定罪处罚。

根据《刑法》第217条:以营利为目的,有下列侵犯著作权情形之一,违法所得数额较大或者有其他严重情节的,处三年以下有期徒刑或者拘役,并处或者单处罚金;违法所得数额巨大或者具有其他特别严重情节的,处三年以上七年以下有期徒刑,并处罚金:

1、未经著作权人许可,复制发行其文字作品、音乐、电影、电视、录像作品、计算机软件及其他作品 的;

2、出版他人享有专有出版权的图书的;

3、未经录音录像制作者许可,复制发行其制作的录音录像的;

4、制作、出售假冒他人署名的美术作品的。

根据《刑法》第218条:以营利为目的,销售明知是本法第二百一十七条规定的侵权复制品,违法所得数额巨大的,处三年以下有期徒刑或者拘役,并处或者单处罚金。

总结

对于广大爬虫工程师,如果你开发的爬虫涉及个人信息及隐私,爬虫未遵守Robots协议,爬虫企图通过技术手段绕过反爬机制等,都是触犯了法律的。

对于那些做爬虫的企业,如果涉及到爬取受著作权保护的内容,涉及到公司商业机密等内容,并且用于盈利或者不正当竞争等,也是国家法律所不允许的。

还有就是,"明知故犯"的事情不要做,也不要抱有任何侥幸心理,一定要远离赌博、S情网站,并拒绝为他们提供任何技术支持。

如果公司的主营业务是P2P,并且自己参与了P2P的开发,那么一定要了解清楚自己公司所做的业务是否合规,如果发现不合规,一定要趁早离职。并且不要参与除纯开发以外的其他事宜。

不要参与'外挂软件'的开发。学会保护自己!

如果你是文中介绍过的相关行业中的程序员,那么希望大家第一时间找律师咨询一下,自己是否有触及到法律,以及如何避免和脱身等。

本文只是简单介绍了几种常见的容易被坑的情况,还有很多情况正在发生和即将发生,所以,希望广大程序员们,不要只顾埋头写代码,还要经常抬头看看,审视下自己所做的产品、所在的公司以及所从事的行业。

作为程序员,我们手里的技术就是工具,那么,我们有责任也有义务来保证我们的工具是用在正途的。

最后,技术无罪、人会犯错、知错能改、善莫大焉。

参考资料:

网络爬虫涉及的法律问题(一)
爬虫的法律红线
https://www.zhihu.com/question/37767673

此文章转载自【程序员面试现场】微信公众号,如有不当联系删除。原文链接

继续阅读 »

最近,有很多关于程序员被抓甚至被判刑的新闻在朋友圈疯传:
"某程序员因为接了个外包,帮别人写了个软件,结果这个软件被用于赌博导致被抓。
某公司利用爬虫抓取用户信息,最后被发现,导致该公司的程序员被抓。
某P2P公司暴雷,老板跑路,程序员被抓。
中科大博士卖“外挂”非法牟利300多万,被警方逮捕。"

那么,作为一个程序员,如何避免这些坑呢?怎样尽可能的保护自己呢?
为此,作者特地找自己法律专业的朋友了解了一些常见的问题,如参与爬虫、赌博网站、P2P以及外挂开发是否违法等问题。

总结出了这篇文章,一起探讨一下"技术到底是不是真的无罪?",作为程序员如何避免面向监狱编程!
由于作者并非专业的法律工作从业者,文中法规部分的引用如有偏差,请指正。希望通过本文可以帮助广大程序员们了解一下有哪些自己的人身自由息息相关的坑。

一、爬虫

爬虫,是互联网时代一项普遍运用的网络信息搜集技术。该项技术最早应用于搜索引擎领域,是搜索引擎获取数据来源的支撑性技术之一。

随着数据资源的爆炸式增长,网络爬虫的应用场景和商业模式变得更加广泛和多样,较为常见的有新闻平台的内容汇聚和生成、电子商务平台的价格对比功能、基于气象数据的天气预报应用等等。

网络爬虫技术为数据收集者提供了极大的便利,也给专业网络爬虫公司带来巨大的收益。所以,很多公司都会有爬虫部门,或者负责开发爬虫的团队,在招聘网站上,也随处可见关于"爬虫工程师"的招聘贴。

关于这个问题,一直都是比较难定性的,因为爬虫本身只是个工具,就和菜刀一样,所以很多人都拿"菜刀无罪论"、"技术无罪论"来为爬虫辩护。

从网络爬虫的相关案例来看,爬虫的开发及使用者通常有很多理由为自己辩护:

“我爬取的都是这个网站的公开数据,搜索引擎不也是这么做的吗?”

“这与搜索引擎行为类似,只是使用了自动脚本,这是合理使用行为。”

“我已经遵守了它们的robots协议、该网站没有robots协议”

“这些数据我只是个人研究使用,并没有商业目的”。

那么,爬虫到底犯不犯法?

目前,关于网络爬虫相关的约束,主要是2019年05月28日国家网信办发布的《数据安全管理办法(征求意见稿)》。这份文件主要包含了数据收集、数据处理使用以及数据安全监督管理三个章节。

基本可以确定的是,如果爬虫使用不当,那么爬虫的开发者是有可能触犯法律的,而根据情况不同,获得的刑罚也有可能有差异。

要看开发和使用爬虫是否犯法,需要从爬什么数据、如何爬取数据以及爬到数据之后怎么用三个方面来判断。接下来就简单分析一下:

爬什么数据犯法?

1、属于著作权法保护的作品

有些网站发表的内容,如文章、评论等都是有著作权的,如果只是单纯的通过浏览器查看是不会触犯法律的。

但是,对于有著作权的作品,如果未经著作权人许可,以盈利为目的,对其作品进行复制是会触犯法律的。

根据《中华人民共和国著作权法》第46条:有下列侵权行为的,应当根据情况,承担停止侵害、消除影响、公开赔礼道歉、赔偿损失等民事责任,并可以由著作权行政管理部门给予没收非法所得、罚款等行政处罚:(一)剽窃、抄袭他人作品的;(二)未经著作权人许可,以营利为目的,复制发行其作品的;(三)出版他人享有专有出版权的图书的;(四)未经表演者许可,对其表演制作录音录像出版的;(五)未经录音录像制作者许可,复制发行其制作的录音录像的;(六)未经广播电台、电视台许可,复制发行其制作的广播、电视节目的;(七)制作、出售假冒他人署名的美术作品的。

如果是使用爬虫技术手段爬取数据之后将其保存下来或者传播,并且进行盈利,这种都是属于犯罪的。

2、用户的个人信息或者个人隐私

个人用户的个人信息,即使是用户自己放到一些网站上进行公开或者部分公开,如微博、微信等,不代表这些数据就可以被其他人随便获取!

根据《民法总则》第111条:任何组织和个人需要获取他人个人信息的,应当依法取得并确保信息安全。不得非法收集、使用、加工、传输他人个人信息;
根据《网络安全法》第44条:任何个人和组织不得窃取或者以其他非法方式获取个人信息。因此,如果爬虫在未经用户同意的情况下大量抓取用户的个人信息,则有可能构成非法收集个人信息的违法行为。

所以,如果爬取的数据涉及到个人信息,都是违法的!

还有些爬虫企图绕过权限校验等,爬取用户未公开的信息,如个人私密相册照片等,都是属于侵犯用户的个人隐私的,这种也是违法的。

3、反不正当竞争保护的数据

目前有很多网站中的数据系由用户生成,且该等数据和内容系原告网站的主要竞争力来源。如大众点评上面的店铺评价、评论等信息,携程网上面的关于酒店的评价评论等信息等。

根据《反不正当竞争法》第2条:经营者在市场交易中,应当遵循自愿、平等、公平、诚实信用的原则,遵守公认的商业道德。

那么,未经允许,爬取其他网站的核心数据,很明显并没有遵守《反不正当竞争法》中规定的自愿、平等、公平、诚实信用的原则。
在大众点评诉百度不正当竞争案件、以及新浪微博诉脉脉不正当竞争等案件中,法院都认定被告未经许可抓取、使用原告网站中的数据的行为,违反了诚实信用原则及公认的道德,损害了互联网的市场竞争秩序,损害了原告的竞争优势,从而构成不正当竞争。

因此,如果抓取大众点评、微博、豆瓣电影、知乎等UGC模式的网站上用户发布的信息,并在自己的产品或者服务中发布、使用该等信息,则有较大的风险构成不正当竞争。

怎么爬犯法?

如果是爬取公开的数据,通常不会被认为是侵权。Google、百度等搜索引擎都是这么爬取的。

那么,到底怎么爬数据是有可能触犯法律的呢,主要考虑是否涉及以下两种行为:

未遵守Robots协议

Robots协议是技术界为了解决爬取方和被爬取方之间通过计算机程序完成关于爬取的意愿沟通而产生的一种机制。

根据《互联网搜索引擎服务自律公约》第7条:机器人协议(robots协议)是指互联网站所有者使用robots.txt文件,向网络机器人(Web robots)给出网站指令的协议。具体而言,robots协议是网站所有者通过位于置于网站根目录下的文本文件robots.txt,提示网络机器人哪些网页不应被抓取,哪些网页可以抓取。

根据《互联网搜索引擎服务自律公约》第8条:互联网站所有者设置机器人协议应遵循公平、开放和促进信息自由流动的原则,限制搜索引擎抓取应有行业公认合理的正当理由,不利用机器人协议进行不正当竞争行为,积极营造鼓励创新、公平公正的良性竞争环境。

虽然《互联网搜索引擎服务自律公约》仅适用于中国互联网协会会员单位和自愿加入《中国互联网行业自律公约》的互联网从业单位,但在司法实践中,Robots协议已经被认定构成互联网行业搜索领域内的商业道德。

因此,无视网站设置的Robots协议而随意抓取网站内容的行为将涉嫌构成对《反不正当竞争法》的第2条的违反,即违反诚实信用原则和商业道德的不正当竞争行为。

绕过防护措施对数据的访问,强行突破反爬措施

由于爬虫的批量访问会给网站带来巨大的压力和负担,因此许多网站经营者会采取技术手段,以阻止爬虫批量获取自己网站信息。

所以,很多爬虫工具为了爬取数据,会想办法通过各种手段绕过防护措施,但是,这种行为也是会触犯法律的。

根据《刑法》第285条第二款:违反国家规定,侵入前款规定以外的计算机信息系统或者采用其他技术手段,获取该计算机信息系统中存储、处理或者传输的数据,或者对该计算机信息系统实施非法控制,情节严重的,处三年以下有期徒刑或者拘役,并处或者单处罚金;情节特别严重的,处三年以上七年以下有期徒刑,并处罚金。

企图通过技术手段,绕过网站的反爬机制,都属于《刑法》中规定的"侵入",都是要被处罚的。

怎么用犯法?

很多公司开发的爬虫遵守了Robots协议,也没有爬取不该爬取的数据,难道这样获取到的数据就可以随便使用了吗?其实也不是,如果使用不当,也会触犯法律的。

比如通过爬虫抓取到的数据进行盈利、损害他人利益、造假、诽谤等都是可能触犯法律的。

此外,未经被收集者同意,即使是将合法收集的公民个人信息向他人提供的,也属于刑法第二百五十三条之一规定的“提供公民个人信息”,可能构成犯罪。

小结

在使用爬虫的过程中,爬取的数据类型、爬取数据的方式以及爬取之后的使用都是可能触犯法律的。

其中,使用爬虫得到的数据进行盈利、损害他人利益、不正当竞争等一般都是针对经营者的。

但是对于程序员来说,如果你的老板让你开发的爬虫,是用来爬取用户的个人信息或者个人隐私,并且该爬虫未遵循Robots协议、或者有意的躲避反爬机制就可能触犯到法律了。

二、赌博、S情网站

除了爬虫以外,最近很多关于程序员参与赌博网站的开发,最终被判刑的新闻,那么,如果参与赌博、S情等网站的开发,是不是一定触犯法律呢?
这种情况主要看开发者是不是属于"明知故犯"。

根据《最高人民法院、最高人民检察院、公安部关于办理网络赌博犯罪案件适用法律若干问题的意见》中关于网上开设赌场共同犯罪的认定和处罚规定:

明知是赌博网站,而为其提供下列服务或者帮助的,属于开设赌场罪的共同犯罪,依照刑法第三百零三条第二款的规定处罚:

(一)为赌博网站提供互联网接入、服务器托管、网络存储空间、通讯传输通道、投放广告、发展会员、软件开发、技术支持等服务,收取服务费数额在2万元以上的;

(二)为赌博网站提供资金支付结算服务,收取服务费数额在1万元以上或者帮助收取赌资20万元以上的;

(三)为10个以上赌博网站投放与网址、赔率等信息有关的广告或者为赌博网站投放广告累计100条以上的。

也就是说,如果你作为程序员,你在帮公司开发赌博网站,只要公司付给你的费用超过了2万元以上,那么你就和开设赌场的人是共同犯罪。

除了赌博网站,所有和黄赌毒有关的软件开发都不要参与,明知道是违法或者可能违法的行为,并为其提供技术支持,都是有可能触犯法律的。快播不就是个很好的例子吗。
所以,程序员一定要远离赌博、色情等网站,并拒绝为他们提供技术服务。

三、P2P

最近,P2P频繁暴雷,因为是网络借贷,所以这些暴雷的公司必然是有程序员的,所以,对于这种P2P公司如果涉及违法,那么参与开发的程序员到底算不算从犯?

前段时间,有脉脉用户发帖称"P2P公司暴雷,前端程序员被抓":

一时间,引起了广泛的讨论,有人认为程序员为违法提供了帮助,属于从犯,有人认为程序员可能不知道公司违法,是"不知者不罪"

那么,关于这个情况,知乎上有用户给过专业的解答:

『如果程序员只是单纯的负责开发,只拿合理的死工资,本人对于公司的合法性和P2P的政策不了解,找工作也是通过正规渠道的。』那么就不算从犯。

但是,如果还负责了公司的其他事情,或者没有只拿死工资,找工作也不是正规渠道的,那就另当别论了。重要的是,如果自己明知道公司是非法的,那么肯定就涉及犯罪了。

所以,对于这种做互联网金融的企业的程序员,需要多多了解一下自己公司当前的主营业务是否合法。是否涉及到非法集资、传销等违法行为。

四、外挂

外挂是指利用电脑技术针对一个或多个网络游戏,通过改变软件的部分程序制作而成的作弊程序。制作贩卖游戏外挂也是会受到我国司法机关打击的行为。

根据开发者制作的不同的外挂类型,以及使用方式等,根据以往案例,可能触犯非法经营罪、破坏计算机信息系统罪以及侵犯著作权罪等。

非法经营罪

外挂等违法行为的出现,严重侵害了游戏开发者、运营商以及正常消费者的合法权益,扰乱了互联网游戏经营的正常秩序,破坏了网络游戏产业的良性发展,违反国家规定,情节严重,应按刑法第225条第四项的规定处罚。

根据《刑法》第225条:违反国家规定,有下列非法经营行为之一,扰乱市场秩序,情节严重的,处五年以下有期徒刑或者拘役,并处或者单处违法所得一倍以上五倍以下罚金;情节特别严重的,处五年以上有期徒刑,并处违法所得一倍以上五倍以下罚金或者没收财产:

一)未经许可经营法律、行政法规规定的专营、专卖物品或者其他限制买卖的物品的;

二)买卖进出口许可证、进出口原产地证明以及其他法律、行政法规规定的经营许可证或者批准文件的;

三)未经国家有关主管部门批准非法经营证券、期货、保险业务的,或者非法从事资金支付结算业务的;

四)其他严重扰乱市场秩序的非法经营行为。

破坏计算机信息系统罪

有些外挂会修改网络游戏运行数据、干扰网络游戏服务端计算机信息系统功能、危害计算机信息系统安全的行为,符合破坏计算机信息系统罪的犯罪构成要件。

根据《刑法》第286条:违反国家规定,对计算机信息系统功能进行删除、修改、增加、干扰,造成计算机信息系统不能正常运行,后果严重的,处五年以下有期徒刑或者拘役;后果特别严重的,处五年以上有期徒刑。

侵犯著作权罪

还有些开发者通过非法手段,获取他人享有著作权的计算机软件中的核心程序文件,制作外挂后用以牟利。这种外挂程序虽然与官方客户端程序并不完全一致,但主体结构、功能构成实质性相同,故被告人的行为构成非法复制计算机软件的行为,应以侵犯著作权罪定罪处罚。

根据《刑法》第217条:以营利为目的,有下列侵犯著作权情形之一,违法所得数额较大或者有其他严重情节的,处三年以下有期徒刑或者拘役,并处或者单处罚金;违法所得数额巨大或者具有其他特别严重情节的,处三年以上七年以下有期徒刑,并处罚金:

1、未经著作权人许可,复制发行其文字作品、音乐、电影、电视、录像作品、计算机软件及其他作品 的;

2、出版他人享有专有出版权的图书的;

3、未经录音录像制作者许可,复制发行其制作的录音录像的;

4、制作、出售假冒他人署名的美术作品的。

根据《刑法》第218条:以营利为目的,销售明知是本法第二百一十七条规定的侵权复制品,违法所得数额巨大的,处三年以下有期徒刑或者拘役,并处或者单处罚金。

总结

对于广大爬虫工程师,如果你开发的爬虫涉及个人信息及隐私,爬虫未遵守Robots协议,爬虫企图通过技术手段绕过反爬机制等,都是触犯了法律的。

对于那些做爬虫的企业,如果涉及到爬取受著作权保护的内容,涉及到公司商业机密等内容,并且用于盈利或者不正当竞争等,也是国家法律所不允许的。

还有就是,"明知故犯"的事情不要做,也不要抱有任何侥幸心理,一定要远离赌博、S情网站,并拒绝为他们提供任何技术支持。

如果公司的主营业务是P2P,并且自己参与了P2P的开发,那么一定要了解清楚自己公司所做的业务是否合规,如果发现不合规,一定要趁早离职。并且不要参与除纯开发以外的其他事宜。

不要参与'外挂软件'的开发。学会保护自己!

如果你是文中介绍过的相关行业中的程序员,那么希望大家第一时间找律师咨询一下,自己是否有触及到法律,以及如何避免和脱身等。

本文只是简单介绍了几种常见的容易被坑的情况,还有很多情况正在发生和即将发生,所以,希望广大程序员们,不要只顾埋头写代码,还要经常抬头看看,审视下自己所做的产品、所在的公司以及所从事的行业。

作为程序员,我们手里的技术就是工具,那么,我们有责任也有义务来保证我们的工具是用在正途的。

最后,技术无罪、人会犯错、知错能改、善莫大焉。

参考资料:

网络爬虫涉及的法律问题(一)
爬虫的法律红线
https://www.zhihu.com/question/37767673

此文章转载自【程序员面试现场】微信公众号,如有不当联系删除。原文链接

收起阅读 »

【建议】webview的listenResourceLoading增加返回response header信息

HTML5+

https://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.listenResourceLoading

目前回调只返回url,但是很多时候,通过url无法判断资源类型,这就导致需要再次请求这个url去获取header里的content-type,请求两次,数量多的话,导致网络堵塞。
建议直接在回调里返回header信息。

继续阅读 »

https://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject.listenResourceLoading

目前回调只返回url,但是很多时候,通过url无法判断资源类型,这就导致需要再次请求这个url去获取header里的content-type,请求两次,数量多的话,导致网络堵塞。
建议直接在回调里返回header信息。

收起阅读 »

强烈建议插件市场中的插件提供历史版本下载

优化建议 用户建议 插件开发 分享插件

1、某些插件更新后可能会出现一些意外BUG,需要继续使用上一个版本。
2、有些开发者心态不好,原先开放下载的插件因为某些原因直接上传一个空插件,不提供他人下载。
3、不是所有的插件作者都使用github,就导致根本无法下载历史版本。

1、某些插件更新后可能会出现一些意外BUG,需要继续使用上一个版本。
2、有些开发者心态不好,原先开放下载的插件因为某些原因直接上传一个空插件,不提供他人下载。
3、不是所有的插件作者都使用github,就导致根本无法下载历史版本。

swiper 高度问题记录

需求:在各个平台实现swiper-item的自动高度,底部的"章节、详情、讨论"采用swiper制作的tab选项,可左右滑动。

思路:
1、css的计算属性calc。给swiper组件设置style="height: calc(100vh - 188upx);"
动态计算屏幕高度减去顶部的高度,在h5中测试没有问题,不知道在其它终端会怎么样,没测试过。

2、高度100%不生效应该是父元素没有高度的问题,在实际测试中顶层view设置为100vh,其它包裹的高度都为100%,则swiper-item的高度也会根据内容高度显示

3、nvue 中样式属性不支持百分比,使用 flex:1
可以给page设置:height: 100%;display: flex;flex-direction: column;再给swiper设置flex:1;然后在盒子里再放一个盒子,同样高度100%;然后给它设置overflow: auto;再在盒子里写内容,就行了。 这个没有测试过

4、https://ask.dcloud.net.cn/question/74184 这个通过计算属性获取屏幕高度

5、https://ask.dcloud.net.cn/article/205 这个通过uniapp的API获取高度

const sysInfo = uni.getSystemInfoSync()  
const w = sysInfo.screenWidth;  
const h = sysInfo.screenHeight;  
console.log(`mode > ${sysInfo.model} , info size > W:${w} H:${h}`)  

const screenW = plus.screen.width;  
const screenH = plus.screen.height;  
console.log(`screen size > W: ${screenW} H:${screenH}`);  

const resolutionW = plus.screen.resolutionWidth;  
const resolutionH = plus.screen.resolutionHeight;  
console.log(`resolution size > W:${resolutionW} H:${resolutionH}`)

6、为了兼容各端,建议字体单位为px、宽高为rpx、布局采用flex。参考官方文档:https://ask.dcloud.net.cn/article/35657

继续阅读 »

需求:在各个平台实现swiper-item的自动高度,底部的"章节、详情、讨论"采用swiper制作的tab选项,可左右滑动。

思路:
1、css的计算属性calc。给swiper组件设置style="height: calc(100vh - 188upx);"
动态计算屏幕高度减去顶部的高度,在h5中测试没有问题,不知道在其它终端会怎么样,没测试过。

2、高度100%不生效应该是父元素没有高度的问题,在实际测试中顶层view设置为100vh,其它包裹的高度都为100%,则swiper-item的高度也会根据内容高度显示

3、nvue 中样式属性不支持百分比,使用 flex:1
可以给page设置:height: 100%;display: flex;flex-direction: column;再给swiper设置flex:1;然后在盒子里再放一个盒子,同样高度100%;然后给它设置overflow: auto;再在盒子里写内容,就行了。 这个没有测试过

4、https://ask.dcloud.net.cn/question/74184 这个通过计算属性获取屏幕高度

5、https://ask.dcloud.net.cn/article/205 这个通过uniapp的API获取高度

const sysInfo = uni.getSystemInfoSync()  
const w = sysInfo.screenWidth;  
const h = sysInfo.screenHeight;  
console.log(`mode > ${sysInfo.model} , info size > W:${w} H:${h}`)  

const screenW = plus.screen.width;  
const screenH = plus.screen.height;  
console.log(`screen size > W: ${screenW} H:${screenH}`);  

const resolutionW = plus.screen.resolutionWidth;  
const resolutionH = plus.screen.resolutionHeight;  
console.log(`resolution size > W:${resolutionW} H:${resolutionH}`)

6、为了兼容各端,建议字体单位为px、宽高为rpx、布局采用flex。参考官方文档:https://ask.dcloud.net.cn/article/35657

收起阅读 »

关于uniapp组件覆盖的问题记录

需求:顶部标题、标题下拉筛选菜单、再下面图文列表

问题:下拉菜单滑动时将顶部标题覆盖了

思路方向:
1、遇见问题不要慌:
A、第一条路:查各种技术文档;
B、第二条路:debug测试
C、第三条路:简化所有代码,简化到问题的关键点测试、查资料

2、查看z-index设置,且z-index仅能在定位元素上奏效(例如 position:absolute),可审查dom;
postion的定位包括:static、relative、absolute、fixed
z-index只能在position属性值为relative、absolute、fixed元素上有效。
https://www.cnblogs.com/zhuzhenwei918/p/6112034.html 深入理解css中position属性及z-index属性
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html Flex 布局教程:语法篇

3、z-index只在并行的组件上有效,一个组件包涵在另一个组件里设置z-index就要注意了

4、可用titleNView或用uni-ui的导航栏组件和list组件

5、如果用自定义导航,跨端需要检测顶部高度,这个还没测试过。

6、cover-view组件

继续阅读 »

需求:顶部标题、标题下拉筛选菜单、再下面图文列表

问题:下拉菜单滑动时将顶部标题覆盖了

思路方向:
1、遇见问题不要慌:
A、第一条路:查各种技术文档;
B、第二条路:debug测试
C、第三条路:简化所有代码,简化到问题的关键点测试、查资料

2、查看z-index设置,且z-index仅能在定位元素上奏效(例如 position:absolute),可审查dom;
postion的定位包括:static、relative、absolute、fixed
z-index只能在position属性值为relative、absolute、fixed元素上有效。
https://www.cnblogs.com/zhuzhenwei918/p/6112034.html 深入理解css中position属性及z-index属性
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html Flex 布局教程:语法篇

3、z-index只在并行的组件上有效,一个组件包涵在另一个组件里设置z-index就要注意了

4、可用titleNView或用uni-ui的导航栏组件和list组件

5、如果用自定义导航,跨端需要检测顶部高度,这个还没测试过。

6、cover-view组件

收起阅读 »