2024-08-27



// 引入Node.js的串口通信模块
const SerialPort = require('serialport');
// 引入Modbus工具库
const Modbus = require('js-modbus-slave');
 
// 打开串口
const port = new SerialPort('/dev/ttyUSB0', { baudRate: 9600 });
 
// 创建Modbus从机
const modbusServer = new Modbus.server.Server(port);
 
// 设置寄存器和线圈数据
const coils = new Modbus.datastores.ArrayDataStore(10000); // 线圈数据
const registers = new Modbus.datastores.ArrayDataStore(10000); // 寄存器数据
 
// 设置从机ID
modbusServer.setServerID(1);
 
// 设置数据存储
modbusServer.addDataStore(coils);
modbusServer.addDataStore(registers);
 
// 监听客户端请求
modbusServer.on('error', (err) => {
  console.error('Modbus server error:', err);
});
 
modbusServer.on('data', (data) => {
  console.log('Modbus server received data:', data);
});
 
// 启动Modbus服务器
modbusServer.listen();
 
// 现在,Modbus从机正在运行,等待客户端请求...

这段代码展示了如何在Node.js环境中使用serialportjs-modbus-slave库来创建一个简单的Modbus从机。它设置了串口和从机ID,并为线圈和寄存器数据设置了数据存储。最后,它启动了Modbus服务器并监听事件。这为开发者提供了一个清晰的例子,展示了如何在工业通信中使用Node.js和Modbus协议。

2024-08-27



import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
 
public class C919PhotoGather implements PageProcessor {
 
    private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
 
    @Override
    public Site getSite() {
        return site;
    }
 
    @Override
    public void process(Page page) {
        // 假设页面上有用于下载的图片链接列表,我们通过jQuery选择器提取这些链接
        List<String> imageUrls = page.getHtml().$("div.g-content img").each(new Function<Element, String>() {
            @Override
            public String apply(Element element) {
                return element.attr("data-original");
            }
        });
 
        // 将提取的图片链接保存到页面对象中,供之后处理
        page.putField("imageUrls", imageUrls);
 
        // 提取下一页链接并加入爬虫的爬取队列
        String nextLink = page.getHtml().$("a.next").links().get();
        page.addTargetRequest(nextLink);
    }
 
    public static void main(String[] args) {
        Spider.create(new C919PhotoGather())
                .addUrl("http://photo.c-star.org/C919/")
                .thread(5)
                .run();
    }
}

这个代码实例展示了如何使用XxlCrawler库来实现一个简单的网页爬虫,该爬虫会从一个模拟的商飞C919相册页面开始,提取该页面上的图片链接,并且跟踪分页,爬取整个相册的所有图片。这个例子教会开发者如何使用XxlCrawler进行基本的网页爬取工作。

2024-08-27

字体反爬通常是指网站通过设置自定义字体(Web Fonts)来保护数据,使得爬虫难以从网页中直接解析出文本内容。这里提供一个基本的方法来处理这种情况:

  1. 分析网站的字体文件:网站通常会在其服务器上提供.woff.woff2等格式的字体文件。你需要下载这些字体文件。
  2. 使用fontTools库来转换字体文件:fontTools是Python中处理字体的库。
  3. 使用pyftsubset工具来提取特定字符的子集字体。
  4. 使用ReportLab库来创建一个简单的PDF,并使用提取出的字体。
  5. 使用OCR技术(如tesseract)来识别图片中的文本。

以下是使用fontToolspyftsubset的示例代码:




from fontTools.ttLib import TTFont
import pyftsubset
 
# 下载的字体文件路径
font_path = 'path_to_font.woff'
 
# 加载字体
font = TTFont(font_path)
 
# 提取子集字体
subset_font = pyftsubset.Subset(font_path, options=['--text=0123456789abcdefghijklmnopqrstuvwxyz'])
with open('subset_font.woff', 'wb') as out:
    out.write(subset_font.subset())
 
# 接下来,你可以使用OCR工具来处理网页截图,并尝试识别文本。
# 例如,使用tesseract识别图片中的文本:
# !tesseract subset_font.woff output -l eng --oem 3 --psm 6 nohup

请注意,这个方法可能不总是有效,因为有些网站采用了更高级的防爬策略,例如动态渲染、JavaScript渲染的内容等。此外,这种方法对于处理复杂的布局和样式可能会有挑战。对于复杂的网站,可能需要更高级的图像处理和机器学习技术来解决。

2024-08-27



<template>
  <div>
    <input v-model="publicKey" placeholder="请输入RSA公钥" />
    <button @click="encryptData">加密数据</button>
  </div>
</template>
 
<script>
import JSEncrypt from 'jsencrypt/bin/jsencrypt'
 
export default {
  data() {
    return {
      publicKey: '',
    }
  },
  methods: {
    encryptData() {
      const encrypt = new JSEncrypt()
      encrypt.setPublicKey(this.publicKey)
      const encrypted = encrypt.encrypt('需要加密的数据')
      console.log('加密后的数据:', encrypted)
      // 这里可以将加密后的数据发送到后端
    }
  }
}
</script>

这段代码展示了如何在Vue 3应用中使用jsencrypt库进行数据加密。用户在输入框中输入RSA公钥,点击按钮后,会触发encryptData方法,使用公钥对默认的字符串"需要加密的数据"进行加密,并在控制台输出加密后的结果。在实际应用中,你可以替换默认的数据,并将加密后的数据发送到后端进行处理。

2024-08-27

在Java中操作JavaScript脚本并且互相调用,可以使用Java内置的javax.script包。以下是一个简单的例子,展示了如何在Java中执行JavaScript代码,并且调用JavaScript中定义的函数。




import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
 
public class JavaToJavaScript {
    public static void main(String[] args) throws Exception {
        // 创建一个ScriptEngineManager实例
        ScriptEngineManager manager = new ScriptEngineManager();
        // 获取JavaScript引擎
        ScriptEngine engine = manager.getEngineByName("nashorn");
 
        // 定义一个Java中的函数
        engine.put("javaFunction", (Invocable.getInterface(Runnable.class)));
 
        // 执行JavaScript代码
        engine.eval("javaFunction.run = function() { print('Hello from JavaScript'); }");
        
        // 调用JavaScript中定义的函数
        Invocable invocable = (Invocable) engine;
        invocable.invokeFunction("javaFunction.run");
    }
}

在这个例子中,我们首先创建了一个ScriptEngineManager实例,然后通过getEngineByName("nashorn")获取了JavaScript引擎。我们将一个Java的接口实例Runnable放入到引擎的上下文中,并命名为javaFunction。然后我们执行了一段JavaScript代码,这段代码重写了javaFunction.run函数。最后,我们通过Invocable接口调用了JavaScript中定义的这个函数。

这个例子展示了如何在Java代码中直接控制和调用JavaScript代码。这种机制可以用于需要在Java应用程序中嵌入或调用JavaScript逻辑的场景。

2024-08-27



// HTML部分
<ul id="items-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <!-- 更多列表项 -->
</ul>
 
// JavaScript部分
document.addEventListener('DOMContentLoaded', function() {
  var dragSrcEl = null;
 
  function handleDragStart(e) {
    // 保存当前拖动的元素
    dragSrcEl = this;
 
    // 设置拖动效果
    e.dataTransfer.effectAllowed = 'move';
    e.dataTransfer.setData('text/html', this.innerHTML);
  }
 
  function handleDragOver(e) {
    if (e.preventDefault) {
      e.preventDefault(); // 阻止默认行为
    }
 
    e.dataTransfer.dropEffect = 'move'; // 设置拖放视觉效果
 
    // 重新排序列表项
    var afterElement = getDragAfterElement(e.clientY);
    if (afterElement == null) {
      return;
    }
    if (dragSrcEl != this && afterElement != dragSrcEl) {
      dragSrcEl.parentNode.insertBefore(dragSrcEl, afterElement);
    }
  }
 
  function handleDrop(e) {
    // 阻止事件进一步传播
    e.stopPropagation();
 
    // 如果有其他元素被拖动的话,执行移动操作
    if (dragSrcEl != this) {
      dragSrcEl.parentNode.insertBefore(dragSrcEl, this);
    }
  }
 
  function handleDragEnd(e) {
    // 清除拖动元素
    dragSrcEl = null;
  }
 
  // 获取当前拖动元素应该插入的位置
  function getDragAfterElement(y) {
    var draggableElements = [...document.querySelectorAll('#items-list li')];
    for (var i = 0; i < draggableElements.length; i++) {
      var draggableElement = draggableElements[i];
      var rect = draggableElement.getBoundingClientRect();
      var offset = rect.height / 2;
      if (y > rect.top + offset && y < rect.bottom - offset) {
        return draggableElement; // 找到了正确的位置
      }
    }
    return null;
  }
 
  // 添加事件监听器到所有列表项
  var draggableItems = document.querySelectorAll('#items-list li');
  draggableItems.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart, false);
    item.addEventListener('dragover', handleDragOver, false);
    item.addEventListener('drop', handleDrop, false);
    item.addEventListener('dragend', handleDragEnd, false);
  });
});

这段代码实现了一个简单的拖拽排序功能。它首先定义了一些事件处理函数,然后在文档加载完成后,为每个列表项添加了拖动事件

2024-08-27



// 定义一个函数,用于处理JavaScript中的浮点数加法
function floatAddition(arg1, arg2) {
    var r1, r2, m;
    try {
        r1 = arg1.toString().split('.')[1].length;
    } catch (e) {
        r1 = 0;
    }
    try {
        r2 = arg2.toString().split('.')[1].length;
    } catch (e) {
        r2 = 0;
    }
    m = Math.pow(10, Math.max(r1, r2));
    return (arg1 * m + arg2 * m) / m;
}
 
// 使用示例
var result = floatAddition(0.1 + 0.2, 0.3); // 正确的结果应该是 0.6,而不是 0.6000000000000001
console.log(result); // 输出正确的结果

这段代码首先定义了一个名为floatAddition的函数,用于处理两个浮点数的加法。它通过将数字转换为字符串,并分割获取小数部分的长度,来计算小数位数,然后通过乘以和除以10的指数次幂来实现精确的加法运算。这是处理JavaScript浮点数计算中精度问题的一种常见方法。

2024-08-27

JavaScript是一种广泛使用的编程语言,其功能和应用范围非常广泛。然而,对于任何编程语言,都有其自身的特点和需要注意的问题。下面我将列举并详细解释JavaScript的九大主题,包括其特点、应用场景以及注意事项。

  1. 函数(Function)

    JavaScript函数是一种封装了特定功能的代码块,可以在程序中任何需要的地方调用。函数可以有参数,并可以返回一个值。

  2. 对象(Object)

    JavaScript对象是一种复杂的数据类型,它可以储存多个键值对,每个键值对可以是不同的数据类型。对象可以用来创建自定义对象类型,并提供了封装数据和方法的能力。

  3. 作用域(Scope)

    JavaScript作用域决定了变量的可见性和生命周期。JavaScript有两种作用域:全局作用域和局部作用域。局部作用域一般是在函数内部定义的。

  4. 闭包(Closure)

    闭包是一个可以捕获其周围作用域中的变量的函数。闭包可以捕获和存储其外部环境中的数据,即使外部函数已经返回。

  5. 原型链(Prototype Chain)

    JavaScript对象有一个特殊的内部属性,称为原型。当访问对象的属性时,如果没有在该对象上找到,就会检查其原型。这种链式结构称为原型链。

  6. 异步编程(Asynchronous Programming)

    JavaScript是单线程的,但它支持异步编程,这通过回调函数和事件循环实现。异步代码不会阻塞主线程,可以在某个任务完成时执行回调。

  7. DOM操作(DOM Manipulation)

    JavaScript可以通过DOM API来操作HTML文档。这包括查询、修改、添加和删除HTML元素和属性。

  8. BOM操作(BOM Manipulation)

    JavaScript可以通过BOM API操作浏览器窗口。这包括控制浏览器窗口的大小和位置,管理浏览器的历史记录等。

  9. 错误处理(Error Handling)

    JavaScript提供了try-catch语句来处理代码中可能出现的错误。开发者可以使用throw语句手动抛出异常,并用catch块来捕获它们。

以上是JavaScript的九大主题,每个主题都有其特点和应用场景,开发者需要根据实际情况选择合适的方法和技术。

2024-08-27



// 假设我们有一个对象,我们需要遍历它的所有属性
const objectToIterate = {
  key1: 'value1',
  key2: 'value2',
  key3: 'value3'
};
 
// 使用for...in遍历对象的所有可枚举属性(包括原型链中的属性)
for (const prop in objectToIterate) {
  if (objectToIterate.hasOwnProperty(prop)) { // 确保属性是对象自身的而不是继承的
    console.log(`${prop}: ${objectToIterate[prop]}`);
  }
}
 
// 使用Object.keys()获取对象键的数组,然后使用forEach遍历
Object.keys(objectToIterate).forEach(key => {
  console.log(`${key}: ${objectToIterate[key]}`);
});
 
// 使用Object.entries()获取一个键值对数组,然后使用for...of遍历
for (const [key, value] of Object.entries(objectToIterate)) {
  console.log(`${key}: ${value}`);
}
 
// 使用for...of结合Object.values()遍历对象的所有值
Object.values(objectToIterate).forEach(value => {
  console.log(value);
});

以上代码展示了四种遍历对象属性的方法,分别是使用for...in、Object.keys()的forEach、Object.entries()的for...of循环以及结合Object.values()的forEach。每种方法都有其适用场景,开发者可以根据具体需求选择合适的遍历方式。

2024-08-27

在JavaScript中,可以使用以下方法来判断一个字符串是否为空:

  1. 使用if语句和length属性:



let str = " ";
if (str.length === 0) {
    console.log("字符串为空");
} else {
    console.log("字符串不为空");
}
  1. 使用=====来判断字符串是否为一个空字符串:



let str = "";
if (str == "") { // 或使用 === 来进行严格比较
    console.log("字符串为空");
} else {
    console.log("字符串不为空");
}
  1. 使用!运算符来检查字符串是否为空或者undefined



let str;
if (!str) {
    console.log("字符串为空或未定义");
} else {
    console.log("字符串不为空");
}

请注意,上述第三种方法会认为未定义(undefined)的变量以及空字符串""都将被视为空。如果你只想判断空字符串,请使用前两种方法。