chinapython 发表于 2021-6-24 21:49

【原创源码】【python】讯飞听见语音转文字免费版

本帖最后由 chinapython 于 2021-6-24 21:51 编辑

```
# -*- coding: utf-8 -*-
# ☯ Author:******
# ☯ Email : ******@****.***
# ☯ Date: 2021/06/24 20:13
import os
import re
import time
import random
import logging
import datetime
import requests
from logging import handlers
from collections import OrderedDict
from urllib3 import encode_multipart_formdata


# 日志模块
class LogGer(object):
    def __init__(self, name):
      os.makedirs("./log") if not os.path.exists("./log") else None# 创建日志文件文件夹
      get_logger_a = logging.getLogger()
      get_logger_a.setLevel(logging.INFO)# 设置默认级别
      formatter = logging.Formatter('%(levelname)s %(asctime)s %(filename)s: %(message)s')
      log_file_path = './log/{}_{}.log'.format(name, time.strftime('%Y%m%d'))
      rotating_handler = handlers.RotatingFileHandler(
            log_file_path, maxBytes=20 * 1024 * 1024, backupCount=10, encoding='utf-8')
      rotating_handler.setFormatter(formatter)
      get_logger_a.addHandler(rotating_handler)
      stream_handler = logging.StreamHandler()
      stream_handler.setFormatter(formatter)
      get_logger_a.addHandler(stream_handler)
      # 过滤级别:控制台输出INFO和WARNING级别,文件只记录WARNING级别
      info_filter = logging.Filter()
      info_filter.filter = lambda record: record.levelno < logging.WARNING# 设置过滤等级
      warn_filter = logging.Filter()
      warn_filter.filter = lambda record: record.levelno >= logging.WARNING
      # stream_handler.addFilter(info_filter)
      rotating_handler.addFilter(warn_filter)


# 爬虫主程序
class TestSpider:
    LogGer(str(os.path.basename(__file__))[:-3])
    logging.info('system is working now.')

    def __init__(self):
      pass

    # 随机头
    @staticmethod
    def random_ua():
      return "Mozilla/5.0 (Windows NT {}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{} Safari/537.36".format(
            random.choice([
                '10.0; Win64; x64', '10.0; WOW64', '10.0',
                '6.2; WOW64', '6.2; Win64; x64', '6.2',
                '6.1', '6.1; Win64; x64', '6.1; WOW64'
            ]), random.choice([
                '70.0.3538.16', '70.0.3538.67', '70.0.3538.97', '71.0.3578.137', '71.0.3578.30', '71.0.3578.33',
                '71.0.3578.80', '72.0.3626.69', '72.0.3626.7', '73.0.3683.20', '73.0.3683.68', '74.0.3729.6',
                '75.0.3770.140', '75.0.3770.8', '75.0.3770.90', '76.0.3809.12', '76.0.3809.126', '76.0.3809.25',
                '76.0.3809.68', '77.0.3865.10', '77.0.3865.40', '78.0.3904.105', '78.0.3904.11', '78.0.3904.70',
                '79.0.3945.16', '79.0.3945.36', '80.0.3987.106', '80.0.3987.16', '81.0.4044.138', '81.0.4044.20',
                '81.0.4044.69', '83.0.4103.14', '83.0.4103.39', '84.0.4147.30', '85.0.4183.38', '85.0.4183.83',
                '85.0.4183.87', '86.0.4240.22', '87.0.4280.20', '87.0.4280.88', '88.0.4324.27'
            ]))

    # 下载器
    def requester(self, url, retry=3, **kwargs):
      """
      :param url: 必须传入的url
      :param retry: 不需要自己传,自动忽视
      :param kwargs: 传递需要的参数,必须“参数名=参数”
      :return: 返回正常访问的内容或者返回None
      """
      try:
            return requests.request(
                url=url,
                method=kwargs.get('method') if kwargs.get('method') else 'get',
                timeout=kwargs.get('timeout') if kwargs.get('timeout') else 30,
                params=kwargs.get('params'),
                data=kwargs.get('data'),
                files=kwargs.get('files'),
                json=kwargs.get('json'),
                cookies=kwargs.get('cookies'),
                allow_redirects=True if kwargs.get('allow_redirects') in else False,
                proxies={
                  'http': 'http://{}'.format(kwargs.get('proxies')),
                  'https': 'http://{}'.format(kwargs.get('proxies'))
                } if kwargs.get('proxies') else None,
                headers=kwargs.get('headers') if kwargs.get('headers') else {
                  'Accept': '*/*',
                  'Connection': 'close',
                  'Accept-Encoding': 'gzip, deflate, br',
                  'User-Agent': self.random_ua()
                },
                verify=False
            )
      except Exception as e:
            return logging.warning('request error:%s' % e) if retry < 1 else self.requester(url, retry - 1, **kwargs)

    def upload(self, file_path: str, **kwargs: any) -> None or dict:
      c = str(kwargs.get("code")) if kwargs.get("code") and len(str(kwargs.get("code"))) == 16 else "s4Qyl0knnW8pjpDK"
      response = self.requester(
            method="post",
            url="https://www.iflyrec.com/AudioStreamService/v1/audios",
            params={"type": "whole", "folder": f"{random.randint(10000000000000000, 99999999999999999)}"},
            headers={
                'Host': 'www.iflyrec.com',
                'Connection': 'close',
                'User-Agent': self.random_ua(),
                'X-Biz-Id': 'xftj',
                'Content-Type': f'multipart/form-data; boundary=----WebKitFormBoundary{c}',
                'Accept': '*/*',
                'Origin': 'https://www.iflyrec.com',
                'Referer': 'https://www.iflyrec.com/html/addMachineOrder.html',
                'Accept-Encoding': 'gzip, deflate',
                'Accept-Language': 'zh-CN,zh;q=0.9'
            },
            data=encode_multipart_formdata(OrderedDict([
                ("language", (None, 1, 'multipart/form-data')),
                ("id", (None, 'WU_FILE_0', 'multipart/form-data')),
                ('name', (None, os.path.basename(file_path), 'multipart/form-data')),
                ('type', (None, 'audio/wav', 'multipart/form-data')),
                ('lastModifiedDate', (
                  None, datetime.datetime.utcnow().strftime('%a %b %d %Y %H:%M:%S GMT+0800') + " (中国标准时间)",
                  'multipart/form-data'
                )),
                ('size', (None, os.path.getsize(file_path), 'multipart/form-data')),
                ('file', (os.path.basename(file_path), open(file_path, "rb").read(), 'audio/wav')),
            ]), boundary=f'----WebKitFormBoundary{c}'),
            proxies=kwargs.get('proxies')
      )
      # request error
      if response is None:
            return logging.warning(f"上传失败了,请测试网络连接情况,file:{file_path}")
      # response error
      if "uploadedSize" not in response.text:
            return logging.warning(f"上传响应结果中不不包含关键字,file:{file_path}")
      elif response.json().get('biz').get('uploadedSize') is None:
            return logging.warning(f"上传响应中关键值缺失,file:{file_path}")
      return response.json()

    def crc32check(self, fileid: str, crc32: str) -> None or bool:
      response = self.requester(
            url=f"https://www.iflyrec.com/TranscriptOrderService/v1/tempAudios/{fileid}/initAudioInfo?crc32={crc32}",
            method="post",
            headers={
                'Host': 'www.iflyrec.com',
                'Connection': 'close',
                'Accept': 'application/json, text/javascript, */*; q=0.01',
                'X-Requested-With': 'XMLHttpRequest',
                'User-Agent': self.random_ua(),
                'X-Biz-Id': 'xftj',
                'Origin': 'https://www.iflyrec.com',
                'Referer': 'https://www.iflyrec.com/html/addMachineOrder.html',
                'Accept-Encoding': 'gzip, deflate',
                'Accept-Language': 'zh-CN,zh;q=0.9',
            })
      if response is None:
            return logging.warning("校验失败:网络不通...")
      return True if "000000" in response.text else False

    def distinguish(self, path, mode=False):
      response = self.requester(
            method="get" if mode else "post",
            url="https://www.iflyrec.com/TranscriptPreviewService/v1/aiTranscriptPreviews",
            headers={
                'Host': 'www.iflyrec.com',
                'Connection': 'close',
                'Accept': 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
                'User-Agent': "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36",
                'X-Biz-Id': 'xftj',
                'Content-Type': 'application/json;charset=UTF-8',
                'Origin': 'https://www.iflyrec.com',
                'Referer': 'https://www.iflyrec.com/html/addMachineOrder.html',
                'Accept-Encoding': 'gzip, deflate',
                'Accept-Language': 'zh-CN,zh;q=0.9'
            },
            params={"filePath": path, "transcriptLanguage": 1},
            json={"filePath": path, "transcriptLanguage": 1} if mode is False else None,
      )
      if response is None:
            return logging.warning("识别失败:网络故障")
      if mode is False and "true" in response.text:
            return self.distinguish(path, True)

      if mode is True and "speaker" in response.text:
            info = response.json()['biz']['transcriptResult']
            return "".join(*?)"''', info)])
      else:
            return logging.warning("识别失败:未知错误")

    @staticmethod
    def write2txt(path, content):
      with open(path, "a+", encoding="utf-8") as f:
            f.write(content + "\n")

    # 运行入口
    def run(self):
      # 提交数据
      res = self.upload(r"C:\Users\Administrator\Desktop\英语\4.wav")
      if res is None:
            return
      # crc32 验证
      msg = self.crc32check(**{"fileid": res['biz']['fileId'], "crc32": res['biz']['crc32']})
      if msg is not True:
            return
      # 开始识别
      text = self.distinguish(res['biz']['transPreviewPath'])
      print(f"获取响应结果:{text}")


if __name__ == '__main__':
    start = TestSpider()
    start.run()

```
# 自己写的玩的,见笑了......开发30分钟,调试3小时................无奈 无奈------------- 评分啥你随意......留言回复是对我最大的鼓励......
# 这个只能转录中文 和 英文,免费的嘛多多少少有限制的哇, 还有最大限制,不能超过3分钟哦,是不是很鸡肋,我那个音频实际是日文的,没英文的,日文在这里肯定转录不对撒,只是做个测试,大家自由玩耍.....

# 上图:,
.

QQending 发表于 2021-6-27 15:21

chinapython 发表于 2021-6-25 11:30
很抱歉哦,没有接口文档呀...这不是简单套用...复用代码,这些模块都是我之前开发好的....讯飞这边几个 ...

哦哦,我后来想了一下,也是……
有些的确是各位通过抓包分析的,只不过有一些常用的app,github上也有人分析过接口了,官方虽然没放出来,但是似乎也不反对讨论。

还有,这些免费接口限时,可以通过截断音频,再稍微分析下音频的音量,选择没有声音的地方截断,免得截的太突兀,更无法识别了。

不过,似乎免费的接口,不论是语音识别还是翻译,似乎都不太理想。

扯远了,谢谢楼主分享源码

chinapython 发表于 2021-6-25 11:30

QQending 发表于 2021-6-25 01:35
其实我挺好奇,30分钟开发,是不是这里面很多代码都是直接复用直接写好了的,比如日志的参数之类的。
主要 ...
很抱歉哦,没有接口文档呀...这不是简单套用...复用代码,这些模块都是我之前开发好的....讯飞这边几个接口都是通过抓包获取,每个接口功能,如何在众多接口中找出关键接口,接口调通、优化业务流程,这些都要考虑,不是你理解的那样....

chinapython 发表于 2021-6-24 21:58

sam喵喵 发表于 2021-6-24 21:57
感谢分享,是你做的限制还是引用库做了限制啊

那是讯飞网页免费试用,我把他接口化了:lol

QQending 发表于 2021-6-25 01:35

其实我挺好奇,30分钟开发,是不是这里面很多代码都是直接复用直接写好了的,比如日志的参数之类的。
主要还是根据讯飞的接口文档来测试吧。

netspirit 发表于 2021-6-24 21:55

收藏了

自己写的玩的,见笑了......开发30分钟,调试3小时................无奈 无奈------------- 评分啥你随意......留言回复是对我最大的鼓励......

sam喵喵 发表于 2021-6-24 21:57

感谢分享,是你做的限制还是引用库做了限制啊

dadaoshuai1990 发表于 2021-6-24 22:26

666很努力了,加油

继续路过 发表于 2021-6-24 22:34

谢谢分享

jjl 发表于 2021-6-24 23:51

谢谢分享,加油学Python!

zz1181 发表于 2021-6-25 06:45

已经很棒棒啦,谢谢分享

liuzhijie0329 发表于 2021-6-25 06:47

下载去试一试
页: [1] 2 3 4 5 6 7 8 9
查看完整版本: 【原创源码】【python】讯飞听见语音转文字免费版