文章架构
开发场景- 在日常开发过程中, 经常需要参考一些文档。对于在线文档,往往由于网速等原因,用起来总不是那么(ma)顺(fan)心。
- 博文以爬取 PyODPS Docs 为例,整理页面爬取、转换(PDFKit)、文档整合(PyPDF2)的过程。
- 开发工具
实现方案- 基于 bs4 模块标签解析
- 爬取页面,逐层获取获取子链接
- 弃用!未能有效获取到当前主题以及子主题 href 并且不能保证获取到的hrefs的顺序与目录层次结构相对应。
- 基于 正则 定位获取链接
- 有效获取所有 hrefs 并 保证其顺序与目录层次结构的一致性。
代码实现1 获取主页链接# coding: utf-8# ## 爬取 PyODPS[latest] 并转换为 PDF# - 爬取主链接# - 根据主链接爬取子连接# - 参考子链接爬取HTML并转换为PDF# - 将所有 PDF 整合为一个PDF# ---# - 注 :# - PyOdps PDF在线最新版本# - 0.3.12# In[15]:import reimport pdfkitimport pandas as pdfrom urllib import urlopenfrom bs4 import BeautifulSoup# 设置 pandas 显示参数pd.set_option('display.width',200)pd.set_option('display.max_rows',1000)pd.set_option('display.max_columns',50)pd.set_option('display.max_colwidth',500)# ### 爬取主链接# #### 爬取PyODPS Docs主页面# In[9]:url='http://pyodps./zh_CN/latest/index.html'html=urlopen(url).read().decode('utf8')soup=BeautifulSoup(html,'lxml')# #### 取值最新文档首页 API及标题# In[10]:# 主链接 (API)api=soup.find(name='link', attrs={'rel':'canonical'}).get('href')# 获取文档标题title=soup.find('link',attrs={'href':'#','rel':'top'}).get('title').replace(' ','_')# 获取首页超链接 (href)hrefs=[]div_s=soup.find_all(name='div',attrs={'aria-label':'main navigation','role':'navigation'})[0]for tag_a in div_s.find_all(name='a',attrs={'class':'reference internal'}): content_name=tag_a.get_text() url=api+tag_a.get('href') hrefs.append([content_name,url])# #### 美化 DataFrame 显示效果函数# In[20]:'''设置悬停效果'''def hover(hover_color='#ffff99'): return dict(selector='tr:hover', props=[('background-color', '%s' % hover_color)])'''美化DataFrame显示效果'''def display_prettify(df): from IPython.display import HTML styles = [ hover(), dict(selector='th', props=[('font-size', '100%'), ('text-align', 'center')]), dict(selector='td', props=[('text-align', 'left')]), dict(selector='caption', props=[('caption-side', 'left')]) ] return df.style.set_table_styles(styles).set_caption('Hover to highlight.')# #### 首页超连接(href)打印显示# In[13]:df=pd.DataFrame(hrefs, columns=['content_name','href'])display_prettify(df) - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
2 参考主链接,获取子链接# ### 根据主链接爬取子连接# In[ ]:hrefs_2=[] # 有序列表,存储主、子链接并与文档目录层次结构保持一致性for name,url in hrefs: if url not in [hf[1] for hf in hrefs_2]: # href 不在 hrefs_2中,则追加 hrefs_2.append([name,url]) t_html=urlopen(url).read().decode('utf8') # 根据正则表达式 查找当前目录主题 f_re='class='current reference internal'.*?' if len(re.findall(f_re, t_html, re.I|re.S|re.M)) !=0 : target_s = re.findall(f_re, t_html, re.I|re.S|re.M)[0] # 根据正则表达式 获取当前子主题链接 t_re='class='reference internal' href='(.*?)'>(.*?)' for href,name in re.findall(t_re, target_s, re.I|re.S|re.M): if href.strip().endswith('.html'): hrefs_2.append([name,api+href])# In[22]:display_prettify(pd.DataFrame(hrefs_2))# #### 显示PyODPS 所有链接# In[105]:pd.DataFrame(hrefs_2) - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
3 根据链接,爬取页面并转换为 PDFs# ### 参考子链接爬取HTML并转换为PDF# In[24]:for name,href in hrefs_2: pdfkit.from_url(href,'./tmp/'+name+'.pdf') from PyPDF2 import PdfFileMerger# 创建 PdfFileMerger 对象,合并PDFsmerger = PdfFileMerger()for name, url in hrefs_2: t_input = open('./tmp/'+name+'.pdf', 'rb') merger.append(t_input)# 流输出output = open(title+'.pdf', 'wb')merger.write(output)# 关闭文件流output.close()merger.close()
脚本链接
Reference Links
|