分享

Python爬虫系列之四:利用Python爬取PyODPS页面并整合成PDF文档

 ly88 2018-03-20

文章架构

arctile_schema


开发场景

  • 在日常开发过程中, 经常需要参考一些文档。对于在线文档,往往由于网速等原因,用起来总不是那么(ma)顺(fan)心。
  • 博文以爬取 PyODPS Docs 为例,整理页面爬取、转换(PDFKit)、文档整合(PyPDF2)的过程。
  • 开发工具
    • Anaconda
    • Python 2

实现方案

  • 基于 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')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
4 通过 PdfFileMerger 整合 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

脚本链接


Reference Links

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多