思路
- httpclient抓取页面内容
- jsoup解析内容
- leanote的api进行上传
实践过程
登录过程
如果是公开的收藏夹是不要验证的,但这里是自己的收藏内容,页面是需要登录的。
在这里就不模拟登录,直接在页面上进行登录,然后把cookies复制出来,放程序里。
抓取页面内容保存
这里直接使用fluent-hc
库,链式调用很是方便。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12
|
public void GetCollectionPage() throws Exception { String collectId = "<自己收藏夹id>"; String cookie = "<浏览器上获取>"; String collectionPageUrl = "https://www.zhihu.com/collection/"+collectId; String outfilepath = "./testdata/myCollectionPage.html"; Header header =new BasicHeader("Cookie",cookie); Request.Get(collectionPageUrl).userAgent(USEANGEN).addHeader(header).execute().saveContent(new File(outfilepath)); }
|
从收藏夹页面中提取内容
提取回答页面地址
先用浏览器打开要分析的页面,F12,查看页面元素。
把要提取的元素找到,Copy Css Path
,取后面一段,如代码中的select里面内容。
示例代码中div.zh-summary.summary.clearfix a.toggle-expand
就是选出页面收藏回答案的a标签的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
public void GetAnsowInCollection() throws IOException { String outfilepath = "./testdata/myCollectionPage.html"; String select = "div.zh-summary.summary.clearfix a.toggle-expand"; Document doc = Jsoup.parse(new File(outfilepath),"UTF-8","https://www.zhihu.com"); Elements els = doc.select(select); System.out.println("size:"+els.size()); for (Element element : els) { System.out.println(element.attr("href")); }
|
从回答页面提取回答的内容
与上面的方法一样,打开回答页面,找到回答内容所在的元素,如span.RichText.CopyrightRichText-richText
然后就用Document.select方来来选出内容,进行输出和保存。
把内容进行转化
在这里遇到了一些坎,因直接用Element.text()方法,可以得到内容,但格式不好,换行都没有。
如果用Element.html()方法,内容格式有,但内容中有html标签,不好看。
自己用字符操作的一些方法进行了替换。
可以处理p,br等标签,但处理不了a,img,ul,li标签。
于是要找了下前人是怎么做的,在github上找到了项目,把html转化为md格式的。看了下代码,也是用jsoup做的。于是就拿过来用了。https://github.com/pnikosis/jHTML2Md.git
于是p,b,br,a,img,ul,li等标签都处理了。
但还有一个问题,因为知乎上的外链,都是通过link.zhihu.com
来跳转的。所以还要把内容中的链接引用地址进行一次转化。
正则表达式https://link.zhihu.com/\?target=(.*)(?=\))
就是把link地址选出来,再进行替换。
还要进行urldecode,我简化处理,只把:
转化,不严谨,但最求暂时能用,是可以接受的。
示例代码
1 2 3 4
| String str = HTML2Md.convertFile(new File(filename), "UTF-8"); str = str.replaceAll("https://link.zhihu.com/\\?target=(.*)(?=\\))","$1"); str = str.replaceAll("%3A",":");
|
把内容通过api传到leanote上去
直接通过api进行操作就行,参见https://github.com/leanote/leanote/wiki/leanote-api
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public void LeanoteAddNote(String title,String content,String noteAbstract) throws Exception { String token = "<登录获取>"; String apiName = "/note/addNote"; String domain = "leanote.com"; String url ="https://"+domain+"/api"+apiName+"/?token="+token; List<NameValuePair> t = new ArrayList<NameValuePair>(); t.add(new BasicNameValuePair("NotebookId",targetNotebookId)); t.add(new BasicNameValuePair("Title",title)); t.add(new BasicNameValuePair("Abstract",noteAbstract)); t.add(new BasicNameValuePair("IsMarkdown","true")); t.add(new BasicNameValuePair("Content",content)); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(t, "UTF-8" ); String res = Request.Post(url).userAgent(myagent).body(entity).execute().returnContent().asString(); System.out.println(res); }
|
其它
再就是处理分页,处理多条数据,进行循环
总结
这是一个典型的信息流加工过程。
搜集指定内容,整理成自己要要的格式与存储方式。
这里我才几百条数据,都是以文本的形式来处理。
使用到的库
- jsoup
- fluent-hc
- commons-lang
- commons-io
- jHTML2Md