• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Go语言实现自动填写古诗词实例代码

    前言

    “白日依山尽,___”。下句自然填黄河入海流,那么“日月忽其不淹兮,___,___,恐美人之迟暮”,中间两句怎么填呢?

    最近工作中有个需求,就是1500道语文诗词填空题没有答案,现在需要给这些题目大爷们匹配它们对应的答案,好在题目信息都很完整,指出了诗词出处、作者信息。自然想到到网上爬取对应文章信息然后字符串匹配答案。目前做完,效果还可以,基本上所有题目的答案都有了,现把操作流程记录下,做个总结。

    1. 文章信息获取

    网上找了很久,目前发现百度汉语对古诗词收录的比较好,格式也比较规范,整个爬取过程还是比较简单,浏览器分析网站,找到它们的搜索接口:http://hanyu.baidu.com/hanyu/ajax/sugs只需要传一个参数:mainkey,是一个urlencode格式的字符串。接口会返回一个匹配列表,再用作者名称对这个列表做筛选,详细代码如下:

     baseUrl := "http://hanyu.baidu.com/hanyu/ajax/sugs?"
     client := http.Client{
     }
     u, _ := url.Parse(baseUrl)
     q := u.Query()
     q.Set("mainkey", name)
     u.RawQuery = q.Encode()
    
     //添加Header
     req, _ := http.NewRequest("GET", u.String(), nil)
     req.Header.Add("User-Agent", `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36`)
     req.Header.Add("DNT", "1")
     req.Header.Add("Host", "hanyu.baidu.com")
     req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8")
     req.Header.Add("Referer", "http://hanyu.baidu.com/shici/detail?pid=be520db056da43238035dc18bb1e1798tn=sug_click")
     
     resp, errDo := client.Do(req)

    拿到返回值以后,筛选出对应的作者信息。

    //如果有多个搜索结果,比对author是否正确
     respJson.ForEach(func(key, value gjson.Result) bool {
     //先看看有没有display_name
     displayName := value.Get("display_name.0").String()
     sid := value.Get("sid.0").String()
     if len(displayName) == 0 {
     //不是这条记录
     return true
     }
    
     //看看type
     typeStr := value.Get("type.0").String()
     if typeStr == "poemline"{
     //取Source
     displayName = value.Get("source_poem.0").String()
     sid = value.Get("source_poem_sid.0").String()
     }
    
     literatureAuthor := value.Get("literature_author.0").String()
     //author是否一致
     if literatureAuthor == author {
     searchResult.Sid = sid
     searchResult.DisplayName = displayName
     searchResult.Author = literatureAuthor
     return false
     }
     return true // keep iterating
     })

    SearchResult保存了搜索到的结果,根据sid拿到文章页面,解析出其中的文章。

    func GetContent(sid string) (content string, err error) {
     baseUrl := "http://hanyu.baidu.com/shici/detail"
    
     result := make([]string, 0, 0)
     client := http.Client{
     }
    
     u, _ := url.Parse(baseUrl)
     q := u.Query()
     q.Set("pid", sid)
     u.RawQuery = q.Encode()
    
     req, _ := http.NewRequest("GET", u.String(), nil)
     req.Header.Add("User-Agent", `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36`)
     req.Header.Add("DNT", "1")
     req.Header.Add("Host", "hanyu.baidu.com")
     req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8")
     req.Header.Add("Referer", "http://hanyu.baidu.com/shici/detail?pid=be520db056da43238035dc18bb1e1798tn=sug_click")
    
     resp, errDo := client.Do(req)
    
     if errDo != nil || resp.StatusCode != 200 {
     err = errors.New("无法连接百度汉语 " + errDo.Error())
     return
     }
    
     docm, errDoc := goquery.NewDocumentFromResponse(resp)
    
     if errDoc != nil {
     err = errors.New("解析Doc错误 " + errDoc.Error())
     return
     }
    
     //诗词信息都保存在 body_p 的div中,可以通过PuerkitoBio/goquery库获取
     pSelect := docm.Find("#body_p")
     pSelect.Each(func(pos int, selection *goquery.Selection) {
     content := strings.TrimSpace(selection.Text())
     result = append(result, content)
     })
    
     content = strings.Join(result, "")
     return
    }

    目前会爬取百度汉语、古诗词两个网站的数据,如果有更好的数据源,只需要实现Spider接口,在MapSpiderManifest()方法中注册即可。

    type Spider interface {
     GetContent(SearchResult) (string, error)
     FindContent(string, string) (SearchResult, error)
    }
    
    func MapSpiderManifest() map[string]Spider {
     //初始化并且注册所有的Spider
     spiderMap := make(map[string]Spider)
    
     //百度
     baiduSpider := new(BaiduSpider)
     spiderMap["baiduSpider"] = baiduSpider
    
     //古诗文网
     gushiwenSpider := new(GushiwenSpider)
     spiderMap["gushiwenSpider"] = gushiwenSpider
     return spiderMap
    }

    2.诗词句子查找

    古诗文默写,以前上学的时候做的多了,把一句话抠出来,随机选其中几段话让学生默写。一般可以归类为一下几种模式:

    开头留空 :_,[_,...],何人不起故园情。
    末尾留空:俱往矣,_,[_,...]。
    中间留空:月出于东山之上,_,白露横江,

    不管是什么样的模式,就每个填空处来看,只有它前面或者后面有提示句,我们才能知道这个空的答案是什么。也就是说,这样的填空可以自主的找到答案,姑且称之为自主空。而前后都没有提示句的空,只能等待附近有自主空找到了答案,才能找到它本身的答案,用一个图说明更加清晰:

    图中灰色的块因为有提示句,所以可以通过步骤一种爬取下来的文章内容找到对应的答案,填入Blank中,具体的查找算法如下代码所示:

    //已知newFind的PreString,求BlankString和PostString
    func makeWithPreContent(contentsSplit []string, newFind *Find) {
     for l := range contentsSplit {
     if isEqual(contentsSplit[l], newFind.PreString)  l  len(contentsSplit)-1 {
     newFind.BlankString = contentsSplit[l+1]
     if l  len(contentsSplit)-2 {
     newFind.PostString = contentsSplit[l+2]
     }
     newFind.BlankFinish = true
     }
     }
    }
    
    //已知newFind的PostString,求BlankString和PreString
    func makeWithPostContent(contentsSplit []string, newFind *Find) {
     for l := range contentsSplit {
     if isEqual(contentsSplit[l], newFind.PostString)  l > 0 {
     newFind.BlankString = contentsSplit[l-1]
     if l-1 > 0 {
     newFind.PreString = contentsSplit[l-2]
     }
     newFind.BlankFinish = true
     }
     }
    }
    
    // 按标点符号分隔内容
    func SplitByPunctuation(s string) ([]string, []string) {
     regPunctuation, _ := regexp.Compile(`[,,。.??!!;;::]`)
     //匹配标点符号,保存下来。 然后分割字符串
     toPun := regPunctuation.FindAllString(s, -1)
     result := regPunctuation.Split(s, -1)
    
     if len(result[len(result)-1]) == 0 {
     result = result[:len(result)-1]
     }
    
     //去掉前后空格,去掉引号
     for i := range result {
     result[i] = strings.TrimSpace(result[i])
     regQuoting := regexp.MustCompile("[“”‘'']")
     result[i] = regQuoting.ReplaceAllString(result[i], "")
     }
     return result, toPun
    }

    所有的自主块都找到答案后,可以把每个自主块看作一个双向链表的表头,我们所要做的就是遍历每个双向链表,把其中每个节点的答案都通过查找算法找出来。当下一个节点是NULL,或者下个节点是一个自主块时,就停止遍历,处理下一个双向链表。这样,无论给出的需要填空的内容多么复杂,都可以顺利的完整自动填写工作。

    3.效果

    一些常用的文言文或诗词:

    1、 前赤壁赋

    2、 离骚


    项目地址:AncientPoetryFillBlank (本地下载)

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

    您可能感兴趣的文章:
    • go语言实现通过FTP库自动上传web日志
    上一篇:golang json性能分析详解
    下一篇:6行代码快速解决golang TCP粘包问题
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Go语言实现自动填写古诗词实例代码 语言,实现,自动,填写,古诗词,