新手问题 bosonnlp 好像停止服务了,调用百度的 api 总是不对,业余程序员求教

lukefan · 2020年10月16日 · 最后由 lukefan 回复于 2020年11月17日 · 972 次阅读

我有一个小应用,用 ruby on rails 去爬一些电视剧资源 原来是使用 bosonnlp 的 api 来计算美剧标题和简介中的关键词

最近发现 boson 好像是停止服务了 于是尝试使用 baidu 的 nlp api

因为是业余程序员,所以先在网上抄了一段代码:

可以 post 到 baidu 的那些 https 的网址上

require 'json'
require 'net/https'
require 'open-uri'

#url:对应的https请求
#toSend:对应的参数{:name => 'lzy'} 形式
   def send_post(url,toSend)
    uri = URI(url)
    http = Net::HTTP.new(uri.host, uri.port)
        if uri.scheme == "https"
            http.use_ssl = true
            http.verify_mode = OpenSSL::SSL::VERIFY_NONE 
        end
    req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
    req.set_form_data(toSend)
    res = http.request(req)
    return JSON.parse res.body
    end

然后参考百度说明:https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu 获取 access_token

params = {}
params[:grant_type] = 'client_credentials'
params[:client_id] = 'client_id'
params[:client_secret] = 'client_secret'
send_post 'https://aip.baidubce.com/oauth/2.0/token', params

成功获取了 access_token 下一步需要提取关键词了,就怎么都不对了。 依据百度的说明:https://ai.baidu.com/ai-doc/NLP/7k6z52ggx

代码如下:

params = {}
params[:access_token] = "#{access_token}"
params[:title] = 'iphone手机出现“白苹果”原因及解决办法,用苹果手机的可以看下'
params[:content] = '如果下面的方法还是没有解决你的问题建议来我们门店看下成都市锦江区红星路三段99号银石广场24层01室。在通电的情况下掉进清水,这种情况一不需要拆机处理。尽快断电。用力甩干,但别把机器甩掉,主意要把屏幕内的水甩出来。如果屏幕残留有水滴,干后会有痕迹。^H3 放在台灯,射灯等轻微热源下让水分慢慢散去。'
send_post 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword', params

得到的结果却总是:{"error_code"=>100, "error_msg"=>"Invalid parameter"}

不知道我是差了哪一步? 请大家帮忙指点一下。

不知道 open-uri 默认的字符集是什么? 我一直猜测是编码问题,我曾经加上过 :charset => 'utf-8' 的 params,还是不对。 估计还是需要做一次 iconv。有空再试吧。 看来是没人搭理啊。

lukefan 回复

文档里要求 title 和 content 是 json 参数,你使用了 form 参数,格式不对。access_token 需要为 query 参数。charset 也是 query 参数,需要设置下。 另外,官方的 http 库很垃圾,可以用 http gem 包。 https://github.com/httprb/http

ThxFly 回复

我使用了你推荐的 http,结果还是一样的。



params = {:title => 'iphone手机出现“白苹果”原因及解决办法,用苹果手机的可以看下',:content=>'如果下面的方 法还是没有解决你的问题建议来我们门店看下成都市锦江区红星路三段99号银石广场24层01室。在通电的情况下掉进清水,这种情况一不 需要拆机处理。尽快断电。用力甩干,但别把机器甩掉,主意要把屏幕内的水甩出来。如果屏幕残留有水滴,干后会有痕迹。^H3 放在台 灯,射灯等轻微热源下让水分慢慢散去。'}
k_url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/keyword'
form = {:access_token=>access_token}
r=HTTP.post(k_url,:form=>form,:params=>params)
r.to_s
"{\"error_code\":100,\"error_msg\":\"Invalid parameter\"}"

应该如何调整?

ThxFly 回复

换了一种写法,也是错误的。

body = "title=\"#{params[:title]}\"\&content=\"#{params[:content]}\""

body
"title=\"iphone手机出现“白苹果”原因及解决办法,用苹果手机的可以看下\"&content=\"如果下面的方法还是没有解决你的问题建议来我们门店看下成都市锦江区红星路三段99号银石广场24层01室。在通电的情况下掉进清水,这种情况一不需要拆机处理。尽快断电。用力甩干,但别把机器甩掉,主意要把屏幕内的水甩出来。如果屏幕残留有水滴,干后会有痕迹。^H3 放在台灯,射灯等轻微热源下让水分慢慢散去。\""
form[:charset] = 'UTF-8'
form[:access_token] = access_token
r = HTTP.headers(:accept=>'application/json').post(k_url,:form=>form,:body=>body)
r.to_s
"{\"error_code\":100,\"error_msg\":\"Invalid parameter\"}"

r = HTTP.headers(:accept=>'application/json').post(k_url,:form=>form,:json => params)
r.to_s
"{\"error_code\":100,\"error_msg\":\"Invalid parameter\"}"

我测试了将 params 作为 json,通过 params 传入,或作为字符串,通过 body 传入,也测试了将 params 作为 json 传递给 json 变量。 都失败了。

又做了有一次失败的尝试:

body = "{\"title\":\"#{params[:title]}\",\"content\":\"#{params[:content]}\"}" 
body
"{\"title\":\"iphone手机出现“白苹果”原因及解决办法,用苹果手机的可以看下\",\"content\":\"如果下面的方法还是没有解 决你的问题建议来我们门店看下成都市锦江区红星路三段99号银石广场24层01室。在通电的情况下掉进清水,这种情况一不需要拆机处理。尽快断电。用力甩干,但别把机器甩掉,主意要把屏幕内的水甩出来。如果屏幕残留有水滴,干后会有痕迹。^H3 放在台灯,射灯等轻微热源下让水分慢慢散去。\"}"
r = HTTP.headers('Content-Type' => 'application/json').post(k_url,form: form, body:body)
r.to_s
"{\"error_code\":100,\"error_msg\":\"Invalid parameter\"}"

我尝试了把 body 重新写成了 json 格式,还是错误的。

终于搞对了。

r = HTTP.headers('Content-Type' => 'application/json').post(k_url, body:JSON.generate(params), params: form)
r.parse
{"log_id"=>6317715199120415505, "items"=>[{"score"=>0.997762, "tag"=>"iphone"}, {"score"=>0.861775, "tag"=>"手机"}, {"score"=>0.845657, "tag"=>"苹果"}, {"score"=>0.83649, "tag"=>"苹果公司"}, {"score"=>0.797243, "tag"=>"数码"}]}
//下面的方法也是对的
r = HTTP.headers('Content-Type' => 'application/json').post(k_url, json:params, params: form)

原来一直在用 form 参数往里面传递固定的参数,在获取 token 的过程中也没有问题。 但是到了获取关键词的时候,就不对了。 access_token 和 charset,要放在 params 里面传入。其他信息通过 json 或 body 传入,差别在于使用 json 格式或字符串格式。 作为一个业余程序员,慢慢研究这种东西,也就获得了玩儿游戏的快感了。虽然搞对了,但还是没明白 form 和 params 的差异。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号