下载某乎专栏文章并存为markdown

打印 上一主题 下一主题

主题 972|帖子 972|积分 2916

前言

由于在2月13日,Autojs的作者发出公告将审查所有代码,并在最新版删除了无障碍截图、通知监听等功能,在打开所有版本都会提示强制更新,之前关注的公众号都连夜删除了教程文章,在搜索时,发现教程作者的文章在其它平台还未删除,为了保险起见,备份一下他的文章。由于他写的文章很多,文章将通过爬虫的方式去获取并保存为markdown文件。
参考文章:
实现思路


  • 下载知乎专栏文章存入html
  • 将所有html转换为md
  • 正则提取markdown中的图片链接
  • 下载图片至本地
  • 上传图片至码云图床
  • 使用新图片链接替换原来的图片链接
下载知乎专栏文章存入html

在浏览器按F12打开调试模式,访问专栏链接,查看网络请求,可以发现这个就是我们想要的内容。某乎比较友好,返回的是json,直接json解析即可。


  • 实现代码
  1. def downloadZhuanLanToLocalHtml(zhuanLan,htmlSavePath):
  2.     """
  3.     下载知乎专栏文章存入html
  4.     :param zhuanLan: 专栏地址  https://www.zhihu.com/column/c_1341718720926887936  地址是c_1341718720926887936
  5.     :htmlSavePath: html文件存放路径
  6.     """
  7.     # 获取总的文章数量
  8.     urlIndex=f"https://www.zhihu.com/api/v4/columns/{zhuanLan}/items"
  9.     res=requests.get(urlIndex,headers=headers)
  10.     # 知乎比较友好,返回的是json
  11.     totals=json.loads(res.text)["paging"]["totals"]
  12.     totalPage=totals//100+1  # 获取总页数
  13.     for i in range(totalPage):
  14.         # limit最大是100,超过会报错
  15.         urlpage = 'https://www.zhihu.com/api/v4/columns/{}/items?limit={}&offset={}'.format(zhuanLan, 100, 100*i)
  16.         respage = requests.get(urlpage, headers=headers)
  17.         data=json.loads(respage.content)['data']
  18.         for article in data:
  19.             title=article["title"]
  20.             content=article["content"]
  21.             # 替换标题中的特殊符号,不然创建文件会报错
  22.             with open(f'{htmlSavePath}\\{title.replace("?","").replace("?","")}.html',"w",encoding="utf-8") as f:
  23.                 f.write(content)
  24.     print("下载完成")
复制代码
将所有html转换为md

将保存的html转换为markdown,我们使用第三方库html2text,在使用前请先安装pip install htm2text。
  1. def convertHtml2Markdow(htmlSavePath,mdSavePath):
  2.     '''
  3.     将所有html转换为md
  4.     : htmlSavePath: 存放html文件的文件夹路径
  5.     : mdSavePath:  存放markdown文件的文件夹路径
  6.     '''
  7.     for file in os.listdir(htmlSavePath):
  8.         # 获取文件名称
  9.         filename=os.path.basename(file).split(".")[0]
  10.         text_maker = ht.HTML2Text()
  11.         # 读取html格式文件
  12.         with open(htmlSavePath+"/"+file, 'r', encoding='UTF-8') as f:
  13.             htmlpage = f.read()
  14.         # 处理html格式文件中的内容
  15.         text = text_maker.handle(htmlpage)
  16.         # 写入处理后的内容
  17.         with open(mdSavePath+"/"+filename+".md", 'w', encoding='UTF-8') as f:
  18.             f.write(text)
复制代码
提取markdown文件中的图片链接

获取md文件中的链接,采用正则方式来提取。
  1. def lambdaToGetMarkdownPicturePosition(content):
  2.     """
  3.     从markdownd代码中提取图片链接
  4.     :param content:
  5.     :return:
  6.     """
  7.     # 该正则只适合某乎的文章,其它的请自行调整
  8.     pattern = re.compile(r"!\[.*?\]\([https|http].*?source=.*?\)")
  9.     resultList = pattern.finditer(content)
  10.     urlList = []
  11.     for item in resultList:
  12.         curStr = item.group()
  13.         curStr = curStr.split('(')[1]
  14.         curStr = curStr.strip(')')
  15.         urlList.append(curStr)
  16.         print(curStr)
  17.     return urlList
复制代码
下载图片至本地

将获取到的图片链接,先下载到本地,同时保存号md文件中图片链接和本地图片路径的映射关系,方便后文替换为新的图床的图片链接。
  1. def downloadPic(urls,picSavePath):
  2.     '''
  3.     下载图片至本地
  4.     : urls: 图片路径
  5.     :picSavePath: 本地存放图片的文件夹
  6.     '''
  7.     picMap={}
  8.     for url in urls:
  9.         res=requests.get(url)
  10.         if res.status_code==200:
  11.             savePicName=url.split("/")[-1]
  12.             with open(f"{picSavePath}/{savePicName.split('?')[0]}","wb") as f:
  13.                 f.write(res.content)
  14.             picMap[url]=f"{picSavePath}/{savePicName.split('?')[0]}"
  15.         else:
  16.             print("图片下载失败")
  17.     return picMap
复制代码
上传图片至gitee图床

这一步将本地的图片上传到gitee的图床,gitee提供了开放的api,通过api可以将图片上传至指定仓库。
  1. 开放api地址:
  2. https://gitee.com/api/v5/swagger#/postV5ReposOwnerRepoContentsPath
复制代码

  • 代码实现
  1. def uploadPicToGitee(picFullPath,access_token="你自己的token",owner="登录的用户名",repo="仓库名",branch="存放的分支",giteeRepoSavePath="仓库下某个目录"):
  2.     '''
  3.     上传文件到gitee
  4.     :picFullPath: 本地图片路径
  5.     :giteeRepoSavePath: gitee仓库中文件存放路径
  6.     '''
  7.     headers = {
  8.         'Accept': 'application/json, text/plain, */*',
  9.         'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
  10.         'Connection': 'keep-alive',
  11.         'Content-Type': 'application/json;charset=UTF-8',
  12.         'Origin': 'https://gitee.com',
  13.         'Referer': 'https://gitee.com/api/v5/swagger',
  14.         'Sec-Fetch-Dest': 'empty',
  15.         'Sec-Fetch-Mode': 'cors',
  16.         'Sec-Fetch-Site': 'same-origin',
  17.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
  18.         'sec-ch-ua': '"Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"',
  19.         'sec-ch-ua-mobile': '?0',
  20.         'sec-ch-ua-platform': '"Windows"',
  21.     }
  22.     # 将图片进行bas4编码
  23.     with open(picFullPath,"rb") as f:
  24.         content=base64.b64encode(f.read())
  25.    
  26.     picDir=os.path.dirname(os.path.abspath(picFullPath))
  27.     # 切换目录
  28.     os.chdir(picDir)
  29.     picName=os.path.basename(picFullPath)
  30.     data = {
  31.         'access_token': access_token,
  32.         'content': content,
  33.         'message': f'upload-{picName}',
  34.         'branch': branch,
  35.     }
  36.     # 上传文件需要处理data
  37.     data=MultipartEncoder(fields=data)
  38.     headers['Content-Type']=data.content_type
  39.     res = requests.post(f'https://gitee.com/api/v5/repos/{owner}/{repo}/contents/{giteeRepoSavePath}/{picName}', headers=headers, data=data,verify=False)
  40.     if res.status_code==201 or res.text=='{"message":"A file with this name already exists"}':
  41.         imgUrl=f'https://gitee.com/{owner}/{repo}/raw/{branch}/{giteeRepoSavePath}/{quote(picName)}'
  42.         return imgUrl
  43.     return None
复制代码
运行程序
  1. if __name__=="__main__":
  2.     zhuanLan="c_1341718720926887936"
  3.     htmlSavePath=r"C:\Users\teisyogun\Desktop\脚本\python_learn\test\test"   # 修改为自己html文件的存放地址
  4.     mdSavePath=r"C:\Users\teisyogun\Desktop\脚本\python_learn\test\test-md"  # 修改为md文件的存放地址
  5.     downloadZhuanLanToLocalHtml(zhuanLan,htmlSavePath)
  6.     convertHtml2Markdow(htmlSavePath,mdSavePath)
  7.      
  8.     mdSavePath1=r"C:\Users\teisyogun\Desktop\脚本\python_learn\test\test-md\test3" # gitee长时间上传会报超时错误,如果md文件很多,分成多批次上传
  9.     picSavePath=r"C:\Users\teisyogun\Desktop\脚本\python_learn\test\test-pic"  # 修改为本地图片的存放路径
  10.     #  下面的逻辑就是在完成原md文件中图片链接替换为gitee图床的图片链接
  11.     for root,dirs,files in os.walk(mdSavePath1):
  12.         for filename in files:
  13.             mdFullPath=os.path.join(root,filename)
  14.             mdBakFullPath=os.path.join(root,filename.replace(".md","-bak.md"))
  15.             with open(mdFullPath,"r+",encoding="utf-8") as f,open(mdBakFullPath,"w",encoding="utf-8") as wf:
  16.                 print(mdFullPath)
  17.                 mdContent="".join(f.readlines())
  18.                 urlList=lambdaToGetMarkdownPicturePosition(mdContent)
  19.                 if len(urlList)!=0:
  20.                     picMap=downloadPic(urlList,picSavePath)
  21.                     print(picMap)
  22.                     if bool(picMap):
  23.                         for picUrl in picMap:
  24.                             imgUrl=uploadPicToGitee(picMap[picUrl])
  25.                            
  26.                             print(imgUrl)
  27.                             if imgUrl is not None:
  28.                                 mdContent=mdContent.replace(picUrl,imgUrl)
  29.                             else:
  30.                                 print(f"文件:{filename}中{picMap[picUrl]}替换失败")
  31.                         wf.write(mdContent)
  32.                         print(f"{filename}+===替换完成")
  33.                 else:
  34.                     wf.write(mdContent)
  35.                         
复制代码
最终效果

所有替换后的md文件

打开带图片的文件,查看源码,发现图片中的文件已经被替换。

在预览模式下查看,图片可以正常显示。至此我们完成了所有的功能。

代码

获取完整代码,请在后台回复【专栏】或在评论区留言。
总结

文章中只是简单实现了需求,代码比较乱,欢迎大家评论指正。
本文由【产品经理不是经理】gzh同步发布,欢迎关注

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

前进之路

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表