Ruby调用LMS API解析复杂JSON,提取submission_comments指定字段
搞定嵌套评论提取:Ruby代码修改与新手友好建议
嘿,作为Ruby新手能写出带分页的API请求脚本已经很厉害了!我看你现在的问题是没法从submission_comments数组里拆出单个评论的comment、author_id、author_name字段,直接把整个数组塞到CSV里了对吧?下面我一步步帮你修改代码,同时解释每个关键部分,方便你理解。
先说说当前代码的核心问题
你现在在遍历返回的提交数据时,直接把comments['submission_comments']这个完整数组写入CSV了,但每个提交可能有多条评论,所以得先遍历这个数组,把每条评论的指定字段单独提出来才行。
修改后的完整代码
require 'typhoeus' require 'link_header' require 'json' require 'csv' the_url = 'https://etctetc' token = 'mytoken' api_endpoint = '/api/etc' output_csv = 'C:\Users\me\Desktop\Ruby Canvas course\assignment_comments.csv' # 先初始化CSV,写入包含评论字段的表头 CSV.open(output_csv, 'wb') do |csv| csv << ["user_id", "TII", "comment_content", "comment_author_id", "comment_author_name"] end request_url = "#{the_url}#{api_endpoint}" more_data = true while more_data get_comments = Typhoeus::Request.new( request_url, method: :get, headers: { authorization: "Bearer #{token}" } ) get_comments.on_complete do |response| # 处理分页链接,加个rescue避免没有link头时崩溃 links = LinkHeader.parse(response.headers['link']).links rescue [] next_link = links.find { |link| link['rel'] == 'next' } request_url = next_link.href if next_link # 控制循环:有下一页且返回内容非空时继续 more_data = !next_link.nil? && response.body != "[]" if response.code == 200 data = JSON.parse(response.body) data.each do |submission| # 先拿到当前提交的基础信息 user_id = submission['user_id'] tii_data = submission['turnitin_data'] # 遍历当前提交的所有评论!这是核心修改点 submission['submission_comments'].each do |single_comment| # 提取你要的三个字段 comment_text = single_comment['comment'] author_id = single_comment['author_id'] author_name = single_comment['author_name'] # 把每条评论的信息追加到CSV CSV.open(output_csv, 'a') do |csv| csv << [user_id, tii_data, comment_text, author_id, author_name] end end end else puts "哎呀,请求出错啦!响应码是:#{response.code}" end end get_comments.run end puts "脚本跑完啦!可以去看CSV文件啦😉"
关键修改点详解
- 表头更新:我把表头改成了更清晰的命名,比如
comment_content,避免和变量名混淆,你也可以改成自己喜欢的名字。 - 遍历评论数组:新增了
submission['submission_comments'].each do |single_comment|循环,这样就能逐条处理每个提交下的所有评论,而不是把整个数组丢进去。 - 字段提取:从每条评论对象里单独取出
comment、author_id、author_name,确保CSV里每条行对应一条评论的信息。 - 健壮性优化:在解析
LinkHeader时加了rescue [],如果响应里没有分页链接,不会直接崩溃,而是继续处理当前页的数据。 - 变量命名更清晰:把原来的
comments改成submission,因为这个变量代表的是单个作业提交数据,不是评论,这样代码读起来更顺。
给Ruby新手的额外小技巧
- 调试神器:加个
require 'pp',然后在处理评论前写pp submission['submission_comments'],可以格式化打印出评论的结构,方便你确认字段名有没有写错。 - CSV写入优化:当前代码每次写评论都打开一次CSV文件,数据量大的时候会有点慢。你可以把CSV对象放在循环外面,一直保持打开状态,比如:
这样减少了IO操作,效率会更高。CSV.open(output_csv, 'wb') do |csv| csv << ["user_id", "TII", "comment_content", "comment_author_id", "comment_author_name"] while more_data # 发起请求、处理响应的代码放在这里 data.each do |submission| # ... 处理提交和评论 submission['submission_comments'].each do |single_comment| csv << [user_id, tii_data, comment_text, author_id, author_name] end end end end - 错误防护:可以给JSON解析加个
rescue,比如data = JSON.parse(response.body) rescue nil,然后判断data是否存在再处理,避免返回无效JSON时脚本直接挂掉。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

