备份CSDN博客正文到本地存档

2024-04-23 04:08

本文主要是介绍备份CSDN博客正文到本地存档,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大哥有了新想法,然而没有技术,令人欣慰的是大哥想到了我,于是我便答应免费帮个忙,这是一个基于云的项目,具体细节也就不透露了,然而在实现的过程中,其中一个模块我觉得可以自用,于是我就想把这个模块抽出来,该模块的功能就是将CSDN博客上的文章下载到本地。
假期只完成了一个模板,虽然很垃圾,但是却能满足自用的需求,一直以来,我都很害怕自己喝懵了写的一些感悟放在网上会在某一天再也打不开,事实上,这种事 情确实也发生过很多次。忘记用户,文章被管理员删除,博客被封闭,网站不再维护等都会导致这样的问题,于是我就不得不定期将自己在各个网站注册的博客复制 到一个本地的文档上,包括网易的,百度的,CSDN的,51CTO的,以及老婆的QQ空间的(我总是将内容发布在老婆的QQ上,因为那上面可以畅所欲 言),这么多的网站,如此多的日志,工作量真的不少,久而久之,本地的存档也越来越乱,渐渐的,有很多文章都被遗漏了。特别是CSDN的博客,一直以来, 我都想将其完整的dump到本地,一篇一篇的复制,简直不可能,因为太多了,也找过整站下载器,但是效果不理想。趁此机会,别人委托我做的这个小玩意正好 可以用于此目的,而且比较满意的一点就是dump下来的每一篇文章都裁掉了不相关的内容,比如友情链接,博客访问量以及广告等,唯一被保留的就是正文和正 文的图片资源。
起初我是使用C++手工实现的,然而却需要自行解析HTML文档的各个标签,落实下来就是复杂的字符串解析,其实字符串解析可以堪称是编程的精髓,但是对 于实际做项目,这种工作还是直接使用现有的解析库比较好,后来我发现使用脚本语言更简单,比如使用python,perl,甚至grep/awk/sed 都可以,然而字符编码却始终是一个大问题。通过咨询一个超猛的同事,我认识了htmlparser这个java库,实在是太方便了,它将html文件元素 抽象成了各个类,这样可以很方便的实现过滤,更可贵的是,这种过滤甚至都不用自己实现,htmlparser中自带了过滤功能,你要做的只是重载一些方法 即可,这样就是使用很简单的代码实现这个博客下载功能了,下载完了之后最好将其保存成一个单独的PDF文档,虽然java也可以实现这个功能,然而目前已 经有了很多这样的工具,有现成工具的就不编程实现,这永远是一个真理。
首先看一下效果,然后看一下代码。
保存在本地的存档拥有下面的目录结构,首先是一个顶级目录,以我博客的标题来命名,内部是一个按月份存档的目录集合以及一个index.html索引文件,如下图所示:


展开一个月份存档目录,你将看到本月的文章集合,每一篇文章包含一个目录,如下图所示:


每一篇文章包含的目录中保存有该篇文章包含的所有图片,如果没有包含图片,则目录为空,如下图:

随意打开一篇文章,你将看到该篇文章的标题以及正文,所有的图片也被包含,链接到了该文章的_files目录中的对应图片,如下图:




index.html呈现处以下的样子:


点击每一篇,将跳转到该篇文章
如果你以文本编辑器或者xcode打开每一篇文章或者index.html文件,你将看到其中的大部分链接都被改成了本地的相对路径了,并且删除了大量的无关的内容,这种修改很简单,手工改其实很可以做到,使用程序来做当然更简便些,问题是当你写程序所带来的麻烦超过了手工修改的麻烦时,这种编程就很没有意义,幸运的是,htmlparser可以很简单的做到这一点,一点也不复杂,这样的话这种编程就显得很有意义了。
代码很简单,基本就是几大块:
1.几次遍历-按主页遍历月份信息,按月份存档遍历文章,按每一篇文章遍历图片;
2.解析关键信息,比如标题,文章中的图片等,并填充数据结构。这种事可以通过Filter来完成;
3.根据filter的副作用填充的信息生成目录。

需要说明的是,以下的代码完全是过程化的,没有使用Java语言的OO特性,因此它的数据以及方法完全是static的,没有生成任何对象,我只是想使用htmlparser的API以及java语言IDE的诸多良好的功能,比如方法以及方法参数的自动补全功能,老手或者科班高年级学生可能会较真地说,C/C++的IDE也可以支持这样的功能,如果碰到这样反驳的,我也可以说,其实嘛,汇编语言也是可以自动补全的…另外,代码中有很多的硬编码,其实应该将它们再抽象一下的,或者说定义成变量也可以,只是因为自用,以后也不准备维护,就这么着了。还有,那就是最大的问题,代码有一些bug,比如对于标题中含有奇怪字符的支持,以及错误日志(这很重要)的记录的缺失等等。不管怎么说,代码如下:

[java] view plain copy
  1. <spanstyle="font-family:KaiTi_GB2312;font-size:18px;">importorg.htmlparser.Node;
  2. importorg.htmlparser.NodeFilter;
  3. importorg.htmlparser.Parser;
  4. importorg.htmlparser.filters.TagNameFilter;
  5. importorg.htmlparser.util.NodeList;
  6. importorg.htmlparser.tags.*;
  7. importjava.io.*;
  8. importjava.net.*;
  9. importjava.nio.*;
  10. importjava.util.List;
  11. importjavax.management.*;
  12. /*类名使用test很不规范,然而为了方面胡乱起的名字,可是不管怎么说,它确实是个test*/
  13. publicclasstest{
  14. /*月份文章的月份名称/月份存档URL对的列表*/
  15. finalstaticAttributeListindexList=newAttributeList();
  16. /*每月文章名称/每月文章的URL对的列表*/
  17. finalstaticAttributeListarticleList=newAttributeList();
  18. /*每篇文章图片本地存档地址/每篇文章图片URL对的列表*/
  19. finalstaticAttributeListresourceList=newAttributeList();
  20. /*保存月份以及该月文章本地存档的列表,用于生成目录*/
  21. staticAttributeListmonthList=newAttributeList();
  22. /*用于生成本地存档目录的writer*/
  23. staticOutputStreamWriterindex_handle=null;
  24. staticStringproxy_addr=null;
  25. staticintproxy_port=3128;
  26. /*
  27. *@paramurl网页的URL
  28. *@paramtype类型:1为文本,0为二进制
  29. *@return内容的字节数组
  30. */
  31. publicstaticbyte[]GetContent(Stringurl,inttype){
  32. byteret[]=null;
  33. try{
  34. HttpURLConnectionconn=null;
  35. InputStreamurlStream=null;;
  36. URLsurl=newURL(url);
  37. intj=-1;
  38. if(proxy_addr!=null){
  39. InetSocketAddresssoA=newInetSocketAddress(InetAddress.getByName(proxy_addr),proxy_port);
  40. Proxyproxy=newProxy(Proxy.Type.HTTP,soA);
  41. conn=(HttpURLConnection)surl.openConnection(proxy);
  42. }else{
  43. conn=(HttpURLConnection)surl.openConnection();
  44. }
  45. /*必须加上这一句伪装成Mozilla浏览器,否则CSDN会拒绝连接*/
  46. conn.setRequestProperty("User-Agent","Mozilla/4.0");
  47. conn.connect();
  48. urlStream=conn.getInputStream();
  49. if(type==1){
  50. StringsTotalString="";
  51. BufferedReaderreader=newBufferedReader(newInputStreamReader(urlStream,"UTF-8"));
  52. CharBuffervv=CharBuffer.allocate(1024);
  53. while((j=reader.read(vv.array()))!=-1){
  54. sTotalString+=newString(vv.array(),0,j);
  55. vv.clear();
  56. }
  57. sTotalString=sTotalString.replace('\n','');
  58. sTotalString=sTotalString.replace('\r','');
  59. ret=sTotalString.getBytes();
  60. }else{
  61. ByteBuffervv=ByteBuffer.allocate(1024);
  62. /*CSDN允许最大图片有上限*/
  63. ByteBufferbuffer=ByteBuffer.allocate(5000000);
  64. while((j=urlStream.read(vv.array()))!=-1){
  65. buffer.put(vv.array(),0,j);
  66. vv.clear();
  67. }
  68. ret=buffer.array();
  69. }
  70. }catch(Exceptione){
  71. e.printStackTrace();
  72. //追加出错日志
  73. }
  74. returnret;
  75. }
  76. /*
  77. *@parampath文件路径
  78. *@paramcontent文件内容的字节数组
  79. *@return成功或者失败
  80. */
  81. publicstaticbooleanWriteFile(Stringpath,byte[]content){
  82. try{
  83. FileOutputStreamosw=newFileOutputStream(path);
  84. osw.write(content);
  85. osw.close();
  86. }catch(Exceptione){
  87. e.printStackTrace();
  88. //追加出错日志
  89. returnfalse;
  90. }
  91. returntrue;
  92. }
  93. /*
  94. *@parampath目录路径
  95. *@return成功或者失败
  96. */
  97. publicstaticbooleanMKDir(Stringpath){
  98. try{
  99. Filefp=newFile(path);
  100. if(!fp.exists()){
  101. fp.mkdir();
  102. }
  103. }catch(Exceptione){
  104. e.printStackTrace();
  105. //追加出错日志
  106. returnfalse;
  107. }
  108. returntrue;
  109. }
  110. /*
  111. *@parampath文件路径
  112. *@paramurl文章在blog上的URL
  113. *@paramarticles保存本月存档的列表
  114. *@return无
  115. */
  116. publicstaticvoidHandleHtml(Stringpath,Stringurl,AttributeListarticles){
  117. try{
  118. StringBuffertext=newStringBuffer();
  119. NodeListnodes=HandleText(newString(GetContent(url,1)),3);
  120. Nodenode=nodes.elementAt(0);
  121. Stringtitle=(String)((List<Attribute>)resourceList.asList()).get(0).getValue();
  122. Stringfilepath=path+"/"+title;
  123. List<Attribute>li=resourceList.asList();
  124. /*加入meta信息*/
  125. text.append(newString("<metahttp-equiv=\"Content-Type\"content=\"text/html;chaset=utf-8\"/>"));
  126. text.append("<h1>"+title+"</h1>");
  127. if(node!=null){
  128. Divdv=(Div)node;
  129. text.append(newString(dv.toHtml().getBytes("UTF-8"),"UTF-8"));
  130. }else{
  131. text.append("<h3>Downloaderror</h3>");
  132. }
  133. test.MKDir(filepath+"_files");
  134. articles.add(newAttribute(filepath.split("/",2)[1],title));
  135. for(inti=1;i<li.size();i++){
  136. byte[]imgString=GetContent((String)li.get(i).getValue(),0);
  137. test.WriteFile(filepath+"_files/"+li.get(i).getName()+".gif",imgString);
  138. }
  139. resourceList.clear();
  140. test.WriteFile(filepath+".html",text.toString().getBytes());
  141. }catch(Exceptione){
  142. //追加出错日志
  143. e.printStackTrace();
  144. }
  145. }
  146. /*
  147. *@paramnlistHTML正文的子标签链表
  148. *@paramindex用于索引图片的个数以及当前的图片数
  149. *@return当前的图片数
  150. */
  151. publicstaticintparseImg(NodeListnlist,intindex){
  152. Nodeimg=null;
  153. intcount=nlist.size();
  154. for(inti=0;i<count;i++){
  155. img=nlist.elementAt(i);
  156. if(imginstanceofImageTag){
  157. ImageTagimgtag=(ImageTag)img;
  158. if(!imgtag.isEndTag()){
  159. Stringtitle=(String)((List<Attribute>)resourceList.asList()).get(0).getValue();
  160. /*将图片的URL映射成本地路径*/
  161. resourceList.add(newAttribute(""+index,newString(imgtag.extractImageLocn().getBytes())));
  162. title=title.trim();
  163. imgtag.setImageURL(title+"_files/"+index+".gif");
  164. /*递增本地路径序列*/
  165. index++;
  166. }
  167. }else{
  168. NodeListslist=img.getChildren();
  169. if(slist!=null&&slist.size()>0){
  170. index=test.parseImg(slist,index);
  171. }
  172. }
  173. }
  174. returnindex;
  175. }
  176. /*
  177. *@paramnlistHTML月份存档的子标签链表
  178. *@paramindex无用
  179. *@return无用
  180. */
  181. publicstaticintparseMonthArticle(NodeListnlist,intindex){
  182. Nodeatls=null;
  183. intcount=nlist.size();
  184. for(inti=0;i<count;i++){
  185. atls=nlist.elementAt(i);
  186. if(atlsinstanceofLinkTag){
  187. LinkTaglink=(LinkTag)atls;
  188. indexList.add(newAttribute(link.getLinkText(),link.extractLink()));
  189. }else{
  190. NodeListslist=atls.getChildren();
  191. if(slist!=null&&slist.size()>0){
  192. index=test.parseMonthArticle(slist,index);
  193. }
  194. }
  195. }
  196. returnindex;
  197. }
  198. /*
  199. *@paramnlistHTML标题的子标签链表
  200. *@paramindex无用
  201. *@return无用
  202. */
  203. publicstaticintparseTitle(NodeListnlist,intindex){
  204. Nodetit=null;
  205. intcount=nlist.size();
  206. for(inti=0;i<count;i++){
  207. tit=nlist.elementAt(i);
  208. if(titinstanceofSpan){
  209. Spanspan=(Span)tit;
  210. if(span.getAttribute("class")!=null&&span.getAttribute("class").equalsIgnoreCase("link_title")){
  211. LinkTaglink=(LinkTag)span.childAt(0);
  212. Stringtitle=link.getLinkText();
  213. /*将文件名中不允许的字符替换成允许的字符*/
  214. title=title.replace('/','-');
  215. title=title.trim();
  216. title=title.replace('','-');
  217. resourceList.add(newAttribute("title",title));
  218. }
  219. }else{
  220. NodeListslist=tit.getChildren();
  221. if(slist!=null&&slist.size()>0){
  222. index=test.parseTitle(slist,index);
  223. }
  224. }
  225. }
  226. returnindex;
  227. }
  228. /*
  229. *@paramnlistHTML每月份存档的子标签链表
  230. *@paramindex无用
  231. *@return无用
  232. */
  233. publicstaticintparsePerArticle(NodeListnlist,intindex){
  234. Nodeatl=null;
  235. intcount=nlist.size();
  236. for(inti=0;i<count;i++){
  237. atl=nlist.elementAt(i);
  238. if(atlinstanceofSpan){
  239. Spanspan=(Span)atl;
  240. if(span.getAttribute("class")!=null&&span.getAttribute("class").equalsIgnoreCase("link_title")){
  241. LinkTaglink=(LinkTag)span.childAt(0);
  242. articleList.add(newAttribute(link.getLinkText(),"http://blog.csdn.net"+link.extractLink()));
  243. }
  244. }else{
  245. NodeListslist=atl.getChildren();
  246. if(slist!=null&&slist.size()>0){
  247. index=test.parsePerArticle(slist,index);
  248. }
  249. }
  250. }
  251. returnindex;
  252. }
  253. /*
  254. *@paramnlistHTML分页显示标签的子标签链表
  255. *@paramindex无用
  256. *@return无用
  257. */
  258. publicstaticintparsePage(NodeListnlist,intindex){
  259. Nodepg=null;
  260. intcount=nlist.size();
  261. for(inti=0;i<count;i++){
  262. pg=nlist.elementAt(i);
  263. if(pginstanceofLinkTag){
  264. LinkTaglt=(LinkTag)pg;
  265. if(lt.getLinkText().equalsIgnoreCase("下一页")){
  266. try{
  267. test.HandleText(newString(test.GetContent("http://blog.csdn.net"+lt.extractLink(),1)),2);
  268. }catch(Exceptione){
  269. //追加出错日志
  270. }
  271. }
  272. }
  273. }
  274. returnindex;
  275. }
  276. /*
  277. *@paramnlistHTML作者信息标签的子标签链表
  278. *@paramindex无用
  279. *@return无用
  280. */
  281. publicstaticintparseAuthor(NodeListnlist,intindex){
  282. Nodeaut=null;
  283. intcount=nlist.size();
  284. for(inti=0;i<count;i++){
  285. aut=nlist.elementAt(i);
  286. if(autinstanceofLinkTag){
  287. LinkTaglink=(LinkTag)aut;
  288. resourceList.add(newAttribute("author",link.getLinkText()));
  289. }else{
  290. NodeListslist=aut.getChildren();
  291. if(slist!=null&&slist.size()>0){
  292. index=test.parseAuthor(slist,index);
  293. }
  294. }
  295. }
  296. returnindex;
  297. }
  298. /*
  299. *@paraminput输入的html文档字符串
  300. *@paramskip是否执行的类别
  301. *@return匹配的链表,很多类别通过副作用而起作用
  302. */
  303. publicstaticNodeListHandleText(Stringinput,finalintskip)throwsException{
  304. Parserparser=Parser.createParser(input,"UTF-8");
  305. NodeListnodes=parser.extractAllNodesThatMatch(newNodeFilter(){
  306. publicbooleanaccept(Nodenode){
  307. if(nodeinstanceofDiv){
  308. Divdv=(Div)node;
  309. NodeListnlist=dv.getChildren();
  310. if(dv.getAttribute("id")!=null&&nlist!=null){
  311. if(dv.getAttribute("id").equalsIgnoreCase("article_content")&&skip==3){
  312. parseImg(nlist,0);
  313. returntrue;
  314. }elseif(dv.getAttribute("id").equalsIgnoreCase("article_details")&&skip==3){
  315. parseTitle(nlist,0);
  316. }elseif(dv.getAttribute("id").equalsIgnoreCase("archive_list")&&(skip==1||skip==4)){
  317. parseMonthArticle(nlist,0);
  318. }elseif(dv.getAttribute("id").equalsIgnoreCase("papelist")&&skip==2){
  319. parsePage(nlist,0);
  320. }elseif(dv.getAttribute("id").equalsIgnoreCase("blog_title")&&skip==4){
  321. parseAuthor(nlist,0);
  322. }
  323. }
  324. if(dv.getAttribute("class")!=null&&nlist!=null){
  325. if(dv.getAttribute("class").equalsIgnoreCase("article_title")&&skip==2){
  326. parsePerArticle(nlist,0);
  327. }
  328. }
  329. }
  330. returnfalse;
  331. }
  332. });
  333. returnnodes;
  334. }
  335. /*
  336. *@paramfilepath本地存档的路径
  337. *@paramurl保存本月存档的网页的URL
  338. *@paramarticles保存本月存档的链表
  339. *@return无
  340. */
  341. publicstaticvoidparseMonth(Stringfilepath,Stringurl,AttributeListarticles){
  342. List<Attribute>li=articleList.asList();
  343. try{
  344. HandleText(newString(GetContent(url,1)),2);
  345. }catch(Exceptione){
  346. //追加出错日志
  347. }
  348. test.MKDir(filepath);
  349. for(inti=0;i<li.size();i++){
  350. HandleHtml(filepath,(String)li.get(i).getValue(),articles);
  351. try{
  352. /*慢一点,否则会被认为是恶意行为*/
  353. Thread.sleep(500);
  354. }catch(Exceptione){}
  355. }
  356. articleList.clear();
  357. }
  358. /*
  359. *@paramurlblog入口文章的URL
  360. *@return无
  361. */
  362. publicstaticvoidparseAll(Stringurl){
  363. try{
  364. Stringauthor=null;
  365. HandleText(newString(GetContent(url,1)),4);
  366. author=(String)((List<Attribute>)resourceList.asList()).get(0).getValue();
  367. resourceList.clear();
  368. test.MKDir(author);
  369. List<Attribute>li=indexList.asList();
  370. for(inti=0;i<li.size();i++){
  371. AttributeListarticles=newAttributeList();
  372. monthList.add(newAttribute(li.get(i).getName(),articles));
  373. parseMonth(author+"/"+li.get(i).getName(),(String)li.get(i).getValue(),articles);
  374. }
  375. HandleIndex(author);
  376. }catch(Exceptione){
  377. e.printStackTrace();
  378. }
  379. indexList.clear();
  380. }
  381. /*
  382. *@paramdir本地存档根路径名称
  383. *@return无
  384. */
  385. staticvoidHandleIndex(Stringdir){
  386. try{
  387. index_handle=newOutputStreamWriter(newFileOutputStream(dir+"/index.html"),"GB18030");
  388. Stringheader="<html><head><metahttp-equiv=\"Content-Type\"content=\"text/html;charset=utf-8\"><title>CSDN文章归档</title></head><bodybgcolor=\"white\"text=\"black\"link=\"#0000FF\"vlink=\"#840084\"alink=\"#0000FF\"><hr></div><div><h1class=\"title\"><aname=\"id2747881\"></a>"+dir+"CSDN文章归档</h1></div></div><hr></div><divclass=\"toc\"><p><b>目录</b></p><dl><dt><spanclass=\"preface\"><ahref=\"preface.html\">摘要</a></span></dt>";
  389. Stringtailer="</div></div><hr></body></html>";
  390. index_handle.write(header);
  391. List<Attribute>li=monthList.asList();
  392. for(inti=0;i<li.size();i++){
  393. Stringmindex="<dt><spanclass=\"part\"><h4>"+li.get(i).getName()+"</span></dt><dd><dl>";
  394. AttributeListarticles=(AttributeList)li.get(i).getValue();
  395. List<Attribute>al=articles.asList();
  396. index_handle.write(mindex);
  397. for(intj=0;j<al.size();j++){
  398. Stringper="<dt><spanclass=\"part\"><ahref=\""+al.get(j).getName()+".html\">"+al.get(j).getValue()+"</a></span></dt>";
  399. index_handle.write(per);
  400. }
  401. index_handle.write("</dl></dd>");
  402. }
  403. index_handle.write(tailer);
  404. index_handle.close();
  405. }catch(Exceptione){}
  406. }
  407. /*
  408. *@paramargsargs[0]:blog入口文章的URLargs[1]:代理地址args[2]:代理端口【用法:javaDownBloghttp://blog.csdn.net/dog250192.168.40.199808】
  409. *@return无
  410. */
  411. publicstaticvoidmain(String[]args)throwsException{
  412. parseAll("http://blog.csdn.net/dog250");
  413. /*booleanvalid=false;
  414. if(args.length==1){
  415. valid=true;
  416. }elseif(args.length==2){
  417. proxy_addr=args[1];
  418. valid=true;
  419. }elseif(args.length==3){
  420. proxy_addr=args[1];
  421. proxy_port=Integer.parseInt(args[2]);
  422. valid=true;
  423. }
  424. if(valid){
  425. parseAll(args[0]);
  426. }else{
  427. }*/
  428. }
  429. }</span>

那么,如果使用上面的代码备份你自己的CSDN博客呢?很简单,将dog250改成你的ID即可,我在main方法中注释了一大段的内容,你也可以将其展开,然后他就是通用的了,试试看。

这篇关于备份CSDN博客正文到本地存档的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/927747

相关文章

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

一文教你使用Python实现本地分页

《一文教你使用Python实现本地分页》这篇文章主要为大家详细介绍了Python如何实现本地分页的算法,主要针对二级数据结构,文中的示例代码简洁易懂,有需要的小伙伴可以了解下... 在项目开发的过程中,遇到分页的第一页就展示大量的数据,导致前端列表加载展示的速度慢,所以需要在本地加入分页处理,把所有数据先放

本地搭建DeepSeek-R1、WebUI的完整过程及访问

《本地搭建DeepSeek-R1、WebUI的完整过程及访问》:本文主要介绍本地搭建DeepSeek-R1、WebUI的完整过程及访问的相关资料,DeepSeek-R1是一个开源的人工智能平台,主... 目录背景       搭建准备基础概念搭建过程访问对话测试总结背景       最近几年,人工智能技术

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

Rsnapshot怎么用? 基于Rsync的强大Linux备份工具使用指南

《Rsnapshot怎么用?基于Rsync的强大Linux备份工具使用指南》Rsnapshot不仅可以备份本地文件,还能通过SSH备份远程文件,接下来详细介绍如何安装、配置和使用Rsnaps... Rsnapshot 是一款开源的文件系统快照工具。它结合了 Rsync 和 SSH 的能力,可以帮助你在 li

deepseek本地部署使用步骤详解

《deepseek本地部署使用步骤详解》DeepSeek是一个开源的深度学习模型,支持自然语言处理和推荐系统,本地部署步骤包括克隆仓库、创建虚拟环境、安装依赖、配置模型和数据、启动服务、调试与优化以及... 目录环境要求部署步骤1. 克隆 DeepSeek 仓库2. 创建虚拟环境3. 安装依赖4. 配置模型

DeepSeek模型本地部署的详细教程

《DeepSeek模型本地部署的详细教程》DeepSeek作为一款开源且性能强大的大语言模型,提供了灵活的本地部署方案,让用户能够在本地环境中高效运行模型,同时保护数据隐私,在本地成功部署DeepSe... 目录一、环境准备(一)硬件需求(二)软件依赖二、安装Ollama三、下载并部署DeepSeek模型选

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

springboot 加载本地jar到maven的实现方法

《springboot加载本地jar到maven的实现方法》如何在SpringBoot项目中加载本地jar到Maven本地仓库,使用Maven的install-file目标来实现,本文结合实例代码给... 在Spring Boothttp://www.chinasem.cn项目中,如果你想要加载一个本地的ja