存档

‘语言’ 分类的存档

使用python调用谷歌翻译接口实现英文到中文的翻译

2020年6月27日 评论已被关闭

通过抓包可以看到谷歌的翻译接口需要生成一个token,此功能需要通过js实现。

我们可以使用PyExecJs这个库来实现在python中执行js脚本的功能。

然后直接通过requests调用谷歌翻译接口就行了。

代码如下:

import execjs  
import requests
  
class Py4Js():  
    def __init__(self):  
        self.ctx = execjs.compile(""" 
        function TL(a) { 
        var k = ""; 
        var b = 406644; 
        var b1 = 3293161072; 
         
        var jd = "."; 
        var $b = "+-a^+6"; 
        var Zb = "+-3^+b+-f"; 
     
        for (var e = [], f = 0, g = 0; g < a.length; g++) { 
            var m = a.charCodeAt(g); 
            128 > m ? e[f++] = m : (2048 > m ? e[f++] = m >> 6 | 192 : (55296 == (m & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (m = 65536 + ((m & 1023) << 10) + (a.charCodeAt(++g) & 1023), 
            e[f++] = m >> 18 | 240, 
            e[f++] = m >> 12 & 63 | 128) : e[f++] = m >> 12 | 224, 
            e[f++] = m >> 6 & 63 | 128), 
            e[f++] = m & 63 | 128) 
        } 
        a = b; 
        for (f = 0; f < e.length; f++) a += e[f], 
        a = RL(a, $b); 
        a = RL(a, Zb); 
        a ^= b1 || 0; 
        0 > a && (a = (a & 2147483647) + 2147483648); 
        a %= 1E6; 
        return a.toString() + jd + (a ^ b) 
    }; 
     
    function RL(a, b) { 
        var t = "a"; 
        var Yb = "+"; 
        for (var c = 0; c < b.length - 2; c += 3) { 
            var d = b.charAt(c + 2), 
            d = d >= t ? d.charCodeAt(0) - 87 : Number(d), 
            d = b.charAt(c + 1) == Yb ? a >>> d: a << d; 
            a = b.charAt(c) == Yb ? a + d & 4294967295 : a ^ d 
        } 
        return a 
    } 
    """)  
          
    def getTk(self,text):  
        return self.ctx.call("TL",text)


def google_translate(content):
    '''实现谷歌的翻译'''
    js = Py4Js()
    tk = js.getTk(content)

    if len(content) > 4891:      
        print("翻译的长度超过限制!!!")      
        return    
  
    param = {'tk': tk, 'q': content}  
  
    result = requests.get("""http://translate.google.cn/translate_a/single?client=t&sl=en 
        &tl=zh-CN&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss 
        &dt=t&ie=UTF-8&oe=UTF-8&clearbtn=1&otf=1&pc=1&srcrom=0&ssel=0&tsel=0&kc=2""", params=param)  
  
    #返回的结果为Json,解析为一个嵌套列表  
    trans = result.json()[0]
    ret = ''
    for i in range(len(trans)):
        line = trans[i][0]
        if line != None:
            ret += trans[i][0]

    return ret

ret = google_translate('this is a test of translating from english to chinese')
print(ret)

本文参考git上的TranslateTool这个项目。

分类: Python, 开发 标签: , ,

在centos7上手动搭建lnmp环境

2020年6月20日 评论已被关闭

LNMP 环境是指在 Linux 系统下,由 Nginx + MySQL/MariaDB + PHP 组成的网站服务器架构。

本文档介绍如何在腾讯云云服务器(CVM)上手动搭建 LNMP 环境。

进行手动搭建 LNMP 环境,您需要熟悉 Linux 命令,例如 CentOS 环境下通过 YUM 安装软件 等常用命令,并对所安装软件的使用及版本兼容性比较了解。

分类: mysql, Php, 开发 标签: ,

c++指针和引用的区别

2020年6月10日 评论已被关闭

c++中,指针和引用都是显著提升代码运行效率的特性,很多情况下,两者都可以使用。

其主要区别在于:

  1. 本质上,指针是一个对象,有自己的地址,存放其他对象的地址;而引用只是其他对象的别名,不是一个对象,编译器不为其分配内存空间。
  2. 动态分配内存时,只能用指针保存内存的地址
  3. 不考虑const情形,指针初始化后可以再次指向另一个同类型对象;引用一旦初始化,其指向不再改变
  4. 指针为空值,即空指针nullptr;引用不能为空值,必须在初始化时设置其指向对象
  5. 指针可以进行增减运算,以指向和原来指向对象相邻的对象;引用一般不执行增减操作,如果执行,则是对其引用对象进行增减运算,前提是该对象需要支持增加运算
分类: C/C++, 开发 标签:

c++数组下标操作底层是通过指针算术计算实现的

2020年6月9日 评论已被关闭

在c/c++中,数组可以通过下标来存取其中的元素。

数组名可视为一个常量指针。

数组的下标操作在底层就是通过该指针的算术加减来实现的。即:

a[i] == *(&a[0]+i) == *(a+i) == *(i+a) == i[a]

看这个连续等式,后边两个写法是不是有点不淡定了?

没错!代码确实可以这样写。

#include <iostream>
using namespace std;

int main(){

	int a[] = {1,2,3,4};
	cout << a[2] << endl;

	cout << 2[a] << endl;
	return 0;
}

上边这个代码片段编译完全没有问题,而且运行结果也OK。
神奇吧!

不过这只是个小玩具,可不能用在实际项目中啊。

分类: C/C++, 开发 标签:

c++11特性:使用条件变量condition_variable进行线程间通信

2020年6月9日 评论已被关闭

多线程编程要实现的一个目的就是,线程间协同工作,以提高效率。

既然要协同,相互之间需要有一个通信机制,互通有无。

c++11提供了条件变量condition_variable来实现线程间通信。

线程可以通过条件变量来wait某个事件,其他线程准备好相关数据后,可通过notify唤醒正在等待的线程。

condition_variable需要和一个mutex关联使用。

请看示例代码:

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <chrono>
using namespace std;


queue<int> msglist;
mutex mmsg;
condition_variable cv;

void produce_msg(){
	for(auto i=0; i<100; i++){
		{
			unique_lock<mutex> lk{mmsg};
			msglist.push(i);
		}

		cout << "Producer put a message: " << i << endl;
		cv.notify_all();
	}
}

void consume_msg(const string& cname){
	while(true){
		{
			unique_lock<mutex> lk{mmsg};
			while(msglist.size() == 0){ //must be a loop
				cv.wait(lk);
			}

			cout << "Consumer-" << cname << " woke up." << endl;
			auto i = msglist.front();
			msglist.pop();
			cout << "Consumer-" << cname << " got message: " << i << endl;
		}
		this_thread::sleep_for(chrono::seconds{1});
	}
}

int main(){
	thread tp{produce_msg};
	thread tc1{consume_msg, "C1"};
	thread tc2{consume_msg, "C2"};

	tc1.join();
	tc2.join();

	tp.join();

	return 0;
}

我们在main中定义了三个线程,tp为生产者,tc1和tc2为消费者。
这三个线程共同存取队列msglist,所以需要通过互斥量mmsg进行同步。
消费者线程启动后,通过条件变量cv.wait()实现阻塞,等待新消息的产生。wait()会释放持有的互斥量mmsg,直到被唤醒时重新加锁。
生产者线程tp向msglist放入一个消息后,就释放互斥量,并通过条件变量cv.notify_all()唤醒两个消费者。
两个消费者被唤醒后,会对互斥量进行竞争性加锁,加锁成功者从队列msglist中取的消息,并短暂sleep,以便另一个消费者有机会获取消息。

需要注意,在consume_msg中wait()是置于一个循环中的。

这样做是为了避免多个多个消费者被同时唤醒时,第一个消费者将队列中的消息取出后,后边的消费者不加判断就去取消息,很可能会取空的现象。

这就是通过条件变量进行线程间通信的基本方法。

分类: C/C++, 开发 标签: ,

c++11特性:线程库thread的使用方法

2020年6月8日 评论已被关闭

多线程是提高程序吞吐量和响应时间的一个基本方法。

不同平台都提供了多线程支持,虽然实现原理和使用方法基本相同,但是由于接口不一致,应用程序需要对各线程库进行封装,以屏蔽平台接口差异,实现代码的跨平台运行。

c++11为我们提供了平台统一的多线程接口,有了它,我们可以方便地开发出跨平台的多线程应用程序。

c++11提供的线程对象包括

  • thread:创建一个线程对象,并提供线程控制接口
  • mutex 和 unique_lock:互斥量和锁,用于同步对共享数据的访问

我们通过示例来看一下线程库的基本用法。

注意:通过g++编译多线程程序时,需要指定-pthread参数。否则会报如下错误:

Enable multithreading to use std::thread: Operation not permitted

  • 简单的多线程:各行其事
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <string>
    #include <chrono>
    using namespace std;
    
    //no lock
    void simple(const string& who){
    	for(auto i=0; i<100; i++){
    	      cout << who << " is counting: " << i << endl;
    	      this_thread::sleep_for(chrono::milliseconds(10));
    	}
    	cout << who << " count Done." << endl;
    }
    
    int main(){
    	thread t1{simple, "T1"};
    	thread t2{simple, "T2"};
    
    	t1.join();
    	t2.join();
    
    	return 0;
    }
  • 基本的同步操作:“同时”操作一个变量
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <string>
    #include <chrono>
    using namespace std;
    
    mutex m0;
    int count=9000;
    void f0(){
    	for(auto i=0; i<100; i++){
    	    {
    			unique_lock<mutex> lk{m0};
    			cout << ++count << endl;
    	    }
    
    	    this_thread::sleep_for(chrono::milliseconds(10));
    	}
    }
    
    int main(){
    	thread ta{f0};
    	thread tb{f0};
    
    	ta.join();
    	tb.join();
    
    	return 0;
    }
  • 死锁:
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <string>
    #include <chrono>
    using namespace std;
    
    //dead lock
    mutex m1, m2;
    
    void f1(const string& tname){
    	unique_lock<mutex> lk1{m1};
    	this_thread::sleep_for(chrono::seconds{5});
    	cout << "Thread " << tname << " woke up." << endl;
    
    	unique_lock<mutex> lk2{m2};
    	cout << "Thread " << tname << " Done." << endl;
    }
    
    void f2(const string& tname){
    	unique_lock<mutex> lk2{m2};
    	this_thread::sleep_for(chrono::seconds{5});
    	cout << "Thread " << tname << " woke up." << endl;
    
    	unique_lock<mutex> lk1{m1};
    	cout << "Thread " << tname << " Done." << endl;
    }
    
    int main(){
    	thread t3{f1, "T3"};
    	thread t4{f2, "T4"};
    	
    	t3.join();
    	t4.join();
    
    	return 0;
    }
  • 避免死锁:一次性获取多个互斥量
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <string>
    #include <chrono>
    using namespace std;
    
    //multiple lock
    mutex m3, m4;
    
    void f3(const string& tname, int s){
    	unique_lock<mutex> lk3{m3, defer_lock};
    	unique_lock<mutex> lk4{m4, defer_lock};
    
    	lock(lk3, lk4);
    	this_thread::sleep_for(chrono::seconds{s});
    	cout << "Thread--" << tname << " has waken up." << endl;
    }
    
    int main(){
    	thread t5{f3, "T5", 6};
    	thread t6{f3, "T6", 10};
    
    	t5.join();
    	t6.join();
    
    	return 0;
    }
分类: C/C++, 开发 标签: ,