deepinlinuxv23环境c语言调用网页翻译中文到英语

受别人python作品启发,顺便练一下c语言编程

用到知识点:调用curl库访问http请求,pcre正则查找字符串,json解析翻译结果

先安装3个库

sudo apt-get install libcurl4-openssl-dev
    sudo apt-get install libpcre3-dev
    sudo apt-get install libjson-c-dev

经过反复调试终于通了,感觉比python代码多了好多

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <pcre.h>
#include <unistd.h>
#include <json-c/json.h>

// 全局变量 32位
char g_ig[48] = {0};
char g_tokenkey[128] = {0};
char g_key[24] = {0};
char g_token[64] = {0};
char g_url[256] = {0};

struct MemoryStruct
{
    char *memory;
    size_t size;
};

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if (ptr == NULL)
    {
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
    }

    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
    printf("  memory (%s)\n", mem->memory);
    return realsize;
}

int translate(const char *word, char *translated_text)
{
    struct MemoryStruct chunk;
    chunk.memory = malloc(1);
    chunk.size = 0;

    CURL *curl;
    CURLcode res;
    struct curl_slist *headers = NULL;
    // 初始化libcurl
    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();

    if (curl)
    {
        // 这里需要构造请求URL和数据
        // 示例 URL
        sprintf(g_url, "https://cn.bing.com/ttranslatev3?isVertical=1&IID=translator.5027&IG=%s", g_ig); // 示例 IG
        const char *url = g_url;
        printf("url: %s\n", url);
        // 添加一个HTTP头部
        headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
        if (headers == NULL)
        {
            fprintf(stderr, "curl_slist_append() failed.\n");
            curl_easy_cleanup(curl);
            return 1;
        }
        // 添加另一个HTTP头部
        headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36");
        if (headers == NULL)
        {
            fprintf(stderr, "curl_slist_append() failed.\n");
            curl_slist_free_all(headers);
            curl_easy_cleanup(curl);
            return 1;
        }
        // 设置HTTP头部到CURL句柄
        res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_setopt() failed: %s\n", curl_easy_strerror(res));
            curl_slist_free_all(headers);
            curl_easy_cleanup(curl);
            return 1;
        }
        CURL *hCurl = curl_easy_init();
        curl_easy_setopt(hCurl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(hCurl, CURLOPT_SSL_VERIFYHOST, 0L);

        // 使用 POST 请求
        curl_easy_setopt(curl, CURLOPT_URL, url);
        char post_data[512] = {0};
        sprintf(post_data, "fromLang=zh-Hans&text=%s&to=en-GB&key=%s&token=%s&tryFetchingGenderDebiasedTranslations=true", word, g_key, g_token); // 这里填写你的POST数据
        printf("post_data: %s\n", post_data);
        // curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); // 这里填写你的POST数据

        // 设置写入回调
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
        // 执行请求
        res = curl_easy_perform(curl);

        // 检查请求是否成功
        if (res != CURLE_OK)
        {
            fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        }
        else
        {

            // 解析 JSON 响应
            struct json_object *parsed_json = json_tokener_parse(chunk.memory);
            if (parsed_json == NULL)
            {
                printf("Error parsing JSON\n");
                free(chunk.memory);
                return 3;
            }
            // 确认解析的对象类型是否是数组
            if (json_object_is_type(parsed_json, json_type_array))
            {
                //  printf("解析成功,这是一个JSON数组\n");
                // 获取数组的长度
                int len = json_object_array_length(parsed_json);
                //   printf("数组长度: %d\n", len);
                // 遍历数组
                for (int i = 0; i < len; i++)
                {
                    struct json_object *obj = json_object_array_get_idx(parsed_json, i);
                    if (obj)
                    {
                        // 获取键值对
                        struct json_object *name = json_object_object_get(obj, "translations");
                        if (name && json_object_is_type(name, json_type_array))
                        {
                            int len = json_object_array_length(name);
                            printf("translations 数组长度: %d\n", len);

                            struct json_object *obj = json_object_array_get_idx(name, 0);
                            if (obj)
                            {
                                struct json_object *name = json_object_object_get(obj, "text");
                                if (name && json_object_is_type(name, json_type_string))
                                {
                                    sprintf(translated_text, "%s", json_object_get_string(name));
                                    printf("name : %s\n", translated_text);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                printf("解析成功,但不是一个JSON数组\n");
            }
            // 释放资源

            free(chunk.memory);
            return 0; // 返回翻译后的文本
        }
        // 清理CURL列表和句柄
        curl_slist_free_all(headers);
        // 清理
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    free(chunk.memory);
    return 2;
}
int gethttptofile()
{
    //  printf("Hello, gethttptofile!\n");
    // 1、curl全局初始化,初始化libcurl库(只能调用一次)
    // CURL_GLOBAL_ALL尽可能初始化一切(除了CURL_GLOBAL_ACK_EINTR)
    // CURL_GLOBAL_WIN32表示libcurl会初始化winsock库,如果失败则无法使用socket,windows系统专用
    // CURL_GLOBAL_SSL初始化SSL,(不初始化可能无法使用https)
    // CURL_GLOBAL_DEFAULT初始WIN32和SSL
    // CURL_GLOBAL_ACK_EINTR设置此标志后,curl将在连接或等待数据时确认EINTR条件。否则,curl会等待直到完全超时。(在7.30.0中添加)
    CURLcode init = curl_global_init(CURL_GLOBAL_ALL);
    if (init != CURLE_OK)
    {
        printf("curl全局初始化失败!\n");
        exit(1);
    }
    // 2、初始化curl,返回CURL句柄
    CURL *curl = (struct CURL *)curl_easy_init();
    if (curl == NULL)
    {
        printf("初始化CURL失败!\n");
        exit(1);
    }
    // 3、设置option,各种curl参数的
    curl_easy_setopt(curl, CURLOPT_URL, "https://cn.bing.com/translator");
    // 设置保存位置,使用临时文件或保存到fopen中
    FILE *file = fopen("biying.htm", "w");
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);
    // 各option
    //    1.CURLOPT_URL
    //    设置访问URL
    //    2.CURLOPT_WRITEFUNCTION,CURLOPT_WRITEDATA
    //    通过设定一个回调函数,执行libcurl在接受到数据后用户想进行的操作,通常函数多做数据保存的功能,如处理下载文件。CURLOPT_WRITEDATA 用于表明CURLOPT_WRITEFUNCTION函数中的stream指针的来源,说白了就是设定回调函数的第四个参数的数据类型。回调函数原型为:size_t function( void *ptr, size_t size, size_t nmemb, void *stream);
    //    3.CURLOPT_HEADERFUNCTION,CURLOPT_HEADERDATA
    //    通过设定一个回调函数,执行libcurl在接受到http头数据后用户想进行的操作。CURLOPT_WRITEDATA 传递指针给libcurl,该指针表明CURLOPT_HEADERFUNCTION 函数的stream指针的来源。回调函数原型为 size_t function( void *ptr, size_t size,size_t nmemb, void *stream);
    //    4.CURLOPT_READFUNCTION CURLOPT_READDATA
    //    libCurl需要读取数据传递给远程主机时将调用CURLOPT_READFUNCTION指定的函数,函数原型是:size_t function(void *ptr, size_t size, size_t nmemb,void *stream). CURLOPT_READDATA 表明CURLOPT_READFUNCTION函数原型中的stream指针来源,说白了就是设定回调函数的第四个参数的数据类型。
    //    5.CURLOPT_NOPROGRESS,CURLOPT_PROGRESSFUNCTION,CURLOPT_PROGRESSDATA
    //    跟数据传输进度相关的参数。CURLOPT_PROGRESSFUNCTION 指定的函数正常情况下每秒被libcurl调用一次,为了使CURLOPT_PROGRESSFUNCTION被调 用,CURLOPT_NOPROGRESS必须被设置为false,CURLOPT_PROGRESSDATA指定的参数将作为 CURLOPT_PROGRESSFUNCTION指定函数的第一个参数
    //    6.CURLOPT_TIMEOUT,CURLOPT_CONNECTIONTIMEOUT:
    //    CURLOPT_TIMEOUT 用于设置传输时间,CURLOPT_CONNECTIONTIMEOUT 设置连接等待时间
    //    7.CURLOPT_FOLLOWLOCATION
    //    设置重定位URL
    //    CURLOPT_RANGE: CURLOPT_RESUME_FROM:
    //    断点续传相关设置。CURLOPT_RANGE 指定char *参数传递给libcurl,用于指明http域的RANGE头域,例如:
    //    表示头500个字节:bytes=0-499
    //    表示第二个500字节:bytes=500-999
    //    表示最后500个字节:bytes=-500
    //    表示500字节以后的范围:bytes=500-
    //                       第一个和最后一个字节:bytes=0-0,-1
    //    同时指定几个范围:bytes=500-600,601-999
    //    CURLOPT_RESUME_FROM 传递一个long参数给libcurl,指定你希望开始传递的偏移量。
    //    8.CURLOPT_UPLOAD:
    //    如果第三个参数被设置为1的话,就是让libcurl做好上传的准备。如果传输协议是http的话,uoload就是发送put。
    //    9. CURLOPT_SSL_VERIFYPEER:
    //    第三个参数的缺省值为1.该函数多用于设定curl忽略对网站证书的检查(不管忽略不忽略,curl都是检查的)。
    //    10.CURLOPT_VERBOSE
    //    相当厉害的一个参数,可以向控制台(默认)输出curl接受和发送的数据,输出流可以重定向。
    //    11.CURLOPT_HTTPGET
    //    将curl向服务器交互数据的方式改变为get
    // 4、执行curl的各种操作的请求
    CURLcode curLcode = curl_easy_perform(curl);
    if (curLcode != CURLE_OK)
    {
        printf("curl请求失败:%d!\n", curLcode);
        exit(1);
    }
    //    perform错误码说明:
    //    1.CURLE_OK
    //    任务完成一切都好
    //    2.CURLE_UNSUPPORTED_PROTOCOL
    //    不支持的协议,由URL的头部指定
    //    3.CURLE_COULDNT_CONNECT
    //    不能连接到remote 主机或者代理
    //    4.CURLE_REMOTE_ACCESS_DENIED
    //    访问被拒绝
    //    5.CURLE_HTTP_RETURNED_ERROR
    //    Http返回错误
    //    6.CURLE_READ_ERROR
    //    读本地文件错误
    // 5、读取请求响应的信息
    long totalTime;
    curLcode = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &totalTime);
    if (curLcode != CURLE_OK)
    {
        printf("curl获取信息失败:%d!\n", curLcode);
    }
    printf("CURLINFO_TOTAL_TIME:%ld!\n", totalTime);
    //    getinfo参数
    //    CURLINFO_EFFECTIVE_URL - 最后一个有效的URL地址
    //    CURLINFO_HTTP_CODE - 最后一个收到的HTTP代码
    //    CURLINFO_FILETIME - 远程获取文档的时间,如果无法获取,则返回值为“-1”
    //    CURLINFO_TOTAL_TIME - 最后一次传输所消耗的时间
    //    CURLINFO_NAMELOOKUP_TIME - 名称解析所消耗的时间
    //    CURLINFO_CONNECT_TIME - 建立连接所消耗的时间
    //    CURLINFO_PRETRANSFER_TIME - 从建立连接到准备传输所使用的时间
    //    CURLINFO_STARTTRANSFER_TIME - 从建立连接到传输开始所使用的时间
    //    CURLINFO_REDIRECT_TIME - 在事务传输开始前重定向所使用的时间
    //    CURLINFO_SIZE_UPLOAD - 以字节为单位返回上传数据量的总值
    //    CURLINFO_SIZE_DOWNLOAD - 以字节为单位返回下载数据量的总值
    //    CURLINFO_SPEED_DOWNLOAD - 平均下载速度
    //    CURLINFO_SPEED_UPLOAD - 平均上传速度
    //    CURLINFO_HEADER_SIZE - header部分的大小
    //    CURLINFO_HEADER_OUT - 发送请求的字符串
    //    CURLINFO_REQUEST_SIZE - 在HTTP请求中有问题的请求的大小
    //    CURLINFO_SSL_VERIFYRESULT - 通过设置CURLOPT_SSL_VERIFYPEER返回的SSL证书验证请求的结果
    //    CURLINFO_CONTENT_LENGTH_DOWNLOAD - 从Content-Length: field中读取的下载内容长度
    //    CURLINFO_CONTENT_LENGTH_UPLOAD - 上传内容大小的说明
    //    CURLINFO_CONTENT_TYPE - 下载内容的Content-Type:值,NULL表示服务器没有发送有效的Content-Type:header
    // 6、清理curl句柄
    curl_easy_cleanup(curl);
    // 7、清理全局配置(只能调用一次)
    curl_global_cleanup();
    fclose(file);

    return 0;
}

int getIg(const char *subject, const char *pattern, char *result, int lenIgnorance)
{
    // const char *subject = "This is a test string.IG:\"1F3128B9E5D4487288669FC943AF4D1A\"";
    // const char *pattern = "IG:\"(.*?)\"";
    const char *error;
    int erroffset;
    pcre *re;
    pcre_extra *extra;
    int ovector[48] = {0};

    // 编译正则表达式
    re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
    if (re == NULL)
    {
        printf("PCRE compilation failed at offset %d: %s\n", erroffset, error);
        return 1;
    }

    // 使用额外的编译选项
    extra = pcre_study(re, 0, &error);
    if (error != NULL)
    {
        printf("PCRE study failed: %s\n", error);
        pcre_free(re);
        return 1;
    }

    // 执行正则表达式匹配
    int rc = pcre_exec(re, extra, subject, strlen(subject), 0, 0, ovector, 48);
    if (rc < 0)
    {
        if (rc == PCRE_ERROR_NOMATCH)
        {
            printf("No match found.\n");
        }
        else
        {
            printf("Matching error: %d\n", rc);
        }
    }
    else
    {
        printf("Match found starting at offset %d %.*s\n", ovector[0], ovector[1] - ovector[0] - lenIgnorance - 1, subject + ovector[0] + lenIgnorance);
        strncpy(result, subject + ovector[0] + lenIgnorance, ovector[1] - ovector[0] - lenIgnorance - 1);
    }

    // 释放资源
    pcre_free(re);
    if (extra != NULL)
        pcre_free(extra);

    return 0;
}

/*
 * 功能:获取token
 * */
int getToken()
{
    FILE *file = fopen("biying.htm", "r");
    // 8、操作文件内容
    // 流指针移动到末尾
    fseek(file, 0, SEEK_END);
    // 返回当前流指针位置
    const long i = ftell(file);
    printf("文件长度:%ld!\n", i);
    // 计算完毕记得把流指针归位
    rewind(file);
    // 申请一块能装下整个文件内容的内存区域
    char *a = (char *)malloc(i);
    // fgets(a, i+1,file);
    fread(a, 1, i, file);
    // printf("当前文件内容:%s \n", a);
    getIg(a, "IG:\"(.*?)\"", g_ig, 4);
    printf("ig: %d %s\n", strlen(g_ig), g_ig);
    getIg(a, "params_AbusePreventionHelper = (.*?);", g_tokenkey, 32);
    printf("g_tokenkey: %d %s\n", strlen(g_tokenkey), g_tokenkey);
    int d = strstr(g_tokenkey, ",") - g_tokenkey;
    // printf("key: %d  %.*s\n", d, d, g_tokenkey);
    sprintf(g_key, "%.*s", d, g_tokenkey);
    printf("g_key:   %s\n", g_key);
    int t = strstr(g_tokenkey, "\",") - strstr(g_tokenkey, ",\"") - 2;
    // strncpy(g_token, g_tokenkey + d + 2, t);
    // printf("g_token: d=%d  t=%d\n", d + 2, t);
    sprintf(g_token, "%.*s", t, g_tokenkey + d + 2);
    g_token[t] = '\0';
    printf("g_token: %d  %s\n", strlen(g_token), g_token);
    // 记得释放申请的内存区域
    free(a);
    // 关闭临时文件
    fclose(file);
    return 0;
}

int main(int argc, char *argv[])
{
    char *word = "待翻译的文本";
    if (argc > 1)
    {
        word = argv[1];
    }
    char result_trans[256] = {0};
    int ret = gethttptofile();
    ret = getToken();
    ret = translate(word, result_trans);
    // if (0 == ret)
    // {
    //    printf("翻译结果: %s\n", result_trans);
    //}
    return 0;
}

然后编译运行

gcc -o bingtrans bingtrans.c -lcurl -lpcre -ljson-c
./bingtrans 可持续发展
顺利翻译出来 sustainable development

然后顺便也记录一下原python代码,差距好大,下次如果是要搞这类小工具还是python更简洁

import requests
import re
import json
  
def trans(word):
    flg=re.search(r'[\u4e00-\u9f5a]',word)
    #en-GB 英文
    #zh-Hans 中文,
    from_word,to_word =('zh-Hans','en-GB') if flg else ('en-GB','zh-Hans')
    uri = 'https://cn.bing.com/translator'
    gi = requests.get(uri).text
    ig = re.search(r'IG:"(.*?)"', gi).group(1)
    token = re.search(r'params_AbusePreventionHelper = (.*?);', gi).group(1)
    tokens = token.replace("[", "")
    js = tokens.split(',')
    t = js[1][1:33]
    url = 'https://cn.bing.com/ttranslatev3?isVertical=1&IG={}&IID=translator.5027'.format(ig)
    data = {
        'fromLang': from_word,
        'text': word,
        'to': to_word,
        'token': t,
        'key': js[0],
        'tryFetchingGenderDebiasedTranslations': 'true'
    }
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
    }
    try:
        response = requests.post(url, data=data, headers=headers)
        translations = response.json()[0]['translations']
        translated_text = translations[0]['text']
        return translated_text
    except:
        return "翻译失败"
 
if __name__ == '__main__':
    word="别无选择唯有前行"
    result=trans(word)
    print(result)
#原文字:你说你,想要逃,剩下空心要不要    
#示例结果:You said that you want to escape, and you want to leave the hollow or not
#新文字: There is no choice but to move forward

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值