[python學習] 模仿瀏覽器下載CSDN源文並實現PDF格式備份

Eastmount發表於2015-05-17
        最近突然想給自己的部落格備份下,看了兩個軟體:一個是CSDN部落格匯出軟體,好像現在不能使用了;一個是豆約翰部落格備份專家,感覺都太慢,而且不靈活,想單獨下一篇文章就比較費時。而且我的畢業論文是基於Python自然語言相關的,所以想結合前面的文章用Python實現簡單的功能:
        1.通過網路下載本體的部落格,包括圖片;
        2.在通過Python把HTML轉換成PDF格式;
        3.如果可能,後面可能會寫文章對程式碼採用特定的方式進行處理。

        言歸正傳,直接上程式碼通過兩個方面進行講解。

一. 設定訊息頭下載CSDN文章內容

        獲取一篇文章Python的程式碼如下,如韓寒的新浪部落格:(文章最後的總結有我以前關於Python爬蟲博文連結介紹)

import urllib
content = urllib.urlopen("http://blog.sina.com.cn/s/blog_4701280b0102eo83.html").read()
open('blog.html','w+').write(content)

        但是很多網站都防止這種獲取方式,如CSDN會返回如下html程式碼:“403 Forbidden錯誤”:

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>
        此時通過設定訊息頭或模仿登入,可以偽裝成瀏覽器實現下載。程式碼如下:
#coding:utf-8
import urllib
import urllib2
import cookielib
import string
import time
import re
import sys

#定義類實現模擬登陸下載HTML
class GetInfoByBrowser:

    #初始化操作
    #常見錯誤:AttributeError: .. instance has no attribute 'opener' 是雙下劃線
    def __init__(self):
       socket.setdefaulttimeout(20)
       self.headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0'}
       self.cookie_support = urllib2.HTTPCookieProcessor(cookielib.CookieJar())
       self.opener = urllib2.build_opener(self.cookie_support,urllib2.HTTPHandler)

    #定義函式模擬登陸
    def openurl(self,url):
        urllib2.install_opener(self.opener)
        self.opener.addheaders = [("User-agent",self.headers),("Accept","*/*"),('Referer','http://www.google.com')]
        try:
            result = self.opener.open(url)
            content = result.read()
            open('openurl.html','w+').write(content)
            print content
            print 'Open Succeed!!!'
        except Exception,e:
            print "Exception: ",e
        else:
            return result

    #定義Get請求 新增請求訊息頭,偽裝成瀏覽器
    def geturl(self,get_url):
        result = ""
        try:
            req = urllib2.Request(url = get_url, headers = self.headers)   
            result = urllib2.urlopen(req).read()
            open('geturl.html','w+').write(result)
            type = sys.getfilesystemencoding()      
            print result.decode("UTF-8").encode(type)  #防止中文亂碼
            print 'Get Succeed!!!'
        except Exception,e:
            print "Exception: ",e
        else:
            return result

#呼叫該類獲取HTML
print unicode('呼叫模擬登陸函式openurl:','utf-8')
print unicode('第一種方法 openurl:','utf-8')
getHtml = GetInfoByBrowser()
getHtml.openurl("http://blog.csdn.net/eastmount/article/details/39770543")

print unicode('第二種方法 geturl:','utf-8')
getHtml.geturl("http://blog.csdn.net/eastmount/article/details/39770543")
        執行效果是下載我的文章“[Python學習] 簡單網路爬蟲抓取部落格文章及思想介紹”,兩種方法效果一樣,其中本體兩個檔案geturl.html和openurl.html。該方法執行Python定義類、函式、urllib2和cookielib相關知識。

二. 實現HTML轉PDF格式備份文章

         首先宣告:這部分程式碼實現最終以失敗告終,以後可能還會繼續研究,一方面由於最近太忙;一方面對Linux的欠缺和對Python的掌握不夠,但還是想把這部分寫出來,感覺還是有些東西的,可能對你也有所幫助!感覺好遺憾啊~

1.轉PDF解決方法

        通過網上查閱資料,發現最常見的兩種呼叫Python庫轉PDF的方法:
        方法一:呼叫PDF報表類庫Reportlab,它是線上網站轉PDF
        該庫不屬於Python的標準類庫,所以必須手動下載類庫包並安裝;同時由於涉及到把圖片轉換為PDF,所以還需要Python imaging library(PIL)類庫。
        參考文章:python實現抓取HTML,取出資料,分析,繪出PDF版圖形

        方法二:通過呼叫xhtml2pdf和pisa庫實現HTML轉PDF
        該方法可以實現將靜態的HTML轉換成PDF格式,其中核心程式碼如下,將本地的"1.html"靜態介面轉換為"test.pdf",下面我嘗試採取的方法也是該方法。
# -*- coding: utf-8 -*- 
import sx.pisa3 as pisa 
data= open('1.htm').read()
result = file('test.pdf', 'wb') 
pdf = pisa.CreatePDF(data, result) 
result.close() 
pisa.startViewer('test.pdf') 
        參考文章:python將html轉成PDF的實現程式碼(包含中文)

        方法三:呼叫第三方wkhtmltopdf軟體實現
        該方法並不像Python呼叫第三方那樣有詳細程式碼,很多文章都是基於輸入命令實現。下面三篇文章都是關於wkhtmltopdf的實現。
        參考文章:HTML轉換成PDF工具:wkhtmltopdf 
                         [php]將html批量轉pdf檔案的解決方案,研究有感
                         wkhtmltopdf 生成帶封面、頁首、頁尾、目錄的pdf

2.安裝PIP及介紹

        此時準備介紹通過xhtml2pdf和pisa庫實現HTML轉PDF的功能,首先需要安裝PIP軟體。正如xifeijian大神所說:“作為Python愛好者,如果不知道easy_install或者pip中的任何一個的話,那麼......”。
        easy_insall的作用和perl中的cpan,ruby中的gem類似,都提供了線上一鍵安裝模組的傻瓜方便方式,而pip是easy_install的改進版,提供更好的提示資訊,刪除package等功能。老版本的python中只有easy_install,沒有pip。常見的具體用法如下:
easy_install的用法:
1) 安裝一個包
 $ easy_install <package_name>
 $ easy_install "<package_name>==<version>"
2) 升級一個包
 $ easy_install -U "<package_name>>=<version>"

pip的用法
1) 安裝一個包
 $ pip install <package_name>
 $ pip install <package_name>==<version>
2) 升級一個包 (如果不提供version號,升級到最新版本)
 $ pip install --upgrade <package_name>>=<version>
3)刪除一個包
 $ pip uninstall <package_name>
        第一步:下載PIP軟體
        可以在官網http://pypi.python.org/pypi/pip#downloads下載,同時cd切換到PIP目錄,在通過python setup.py install安裝。而我採用的是下載pip-Win_1.7.exe進行安裝,下載地址如下:
        https://sites.google.com/site/pydatalog/python/pip-for-windows
        第二步:安裝PIP軟體



        當提示"pip and virtualenv installed"表示安裝成功,那怎麼測試PIP安裝成功呢?
        第三步:配置環境變數
        此時在cmd中輸入pip指令會提示錯誤“不是內部或外部命令”,所以需要新增path環境變數。PIP安裝完成後,會在Python安裝目錄下新增python\Scripts目錄,即在python安裝目錄的Scripts目錄下,將此目錄加入環境變數中即可!過程如下:



        第四步:使用PIP命令
        下面在CMD中使用PIP命令,“pip list outdate”列舉Python安裝庫的版本資訊。

       PIP常用的命令如下所示: (參考pip安裝使用詳解)
Usage:   
  pip <command> [options]
 
Commands:
  install                     安裝軟體.
  uninstall                   解除安裝軟體.
  freeze                      按著一定格式輸出已安裝軟體列表
  list                        列出已安裝軟體.
  show                        顯示軟體詳細資訊.
  search                      搜尋軟體,類似yum裡的search.
  wheel                       Build wheels from your requirements.
  zip                         不推薦. Zip individual packages.
  unzip                       不推薦. Unzip individual packages.
  bundle                      不推薦. Create pybundles.
  help                        當前幫助.
 
General Options:
  -h, --help                  顯示幫助.
  -v, --verbose               更多的輸出,最多可以使用3次
  -V, --version               現實版本資訊然後退出.
  -q, --quiet                 最少的輸出.
  --log-file <path>           覆蓋的方式記錄verbose錯誤日誌,預設檔案:/root/.pip/pip.log
  --log <path>                不覆蓋記錄verbose輸出的日誌.
  --proxy <proxy>             Specify a proxy in the form [user:passwd@]proxy.server:port.
  --timeout <sec>             連線超時時間 (預設15秒).
  --exists-action <action>    預設活動當一個路徑總是存在: (s)witch, (i)gnore, (w)ipe, (b)ackup.
  --cert <path>               證照.

3.安裝xhtml2pdf和pisa軟體

        通過PIP命令安裝xhtml2pdf和pisa庫。下載地址:
        xhtml2pdf 0.0.6:https://pypi.python.org/pypi/xhtml2pdf/
        pisa 3.0.33:https://pypi.python.org/pypi/pisa/
        然後通過下面命令安裝:
            pip install xhtml2pdf
            pip install pisa

4.失敗原因

        最初沒有安裝Pisa庫時執行那段HTML轉PDF的程式碼會報錯:
                >>> 
                Traceback (most recent call last):
                File "G:/software/Program software/Python/python insert/HtmlToPDF.py", line 12, in <module>
                ImportError: No module named sx.pisa3

        在安裝完成後不會提示匯入庫名不存在,但此時HTML轉PDF的程式碼會報錯:
****************************************************
IMPORT ERROR!
Reportlab Version 2.1+ is needed!
****************************************************

The following Python packages are required for PISA:
- Reportlab Toolkit >= 2.2 <http://www.reportlab.org/>
- HTML5lib >= 0.11.1 <http://code.google.com/p/html5lib/>

Optional packages:
- pyPDF <http://pybrary.net/pyPdf/>
- PIL <http://www.pythonware.com/products/pil/>

Traceback (most recent call last):
  File "G:\software\Program software\Python\python insert\HtmlToPDF.py", line 5, in <module>
    import sx.pisa3 as pisa
...

raise ImportError("Reportlab Version 2.1+ is needed!")
ImportError: Reportlab Version 2.1+ is needed!

        其原因是匯入"import sx.pisa3 as pisa "時就顯示Reportlab版本需要大於2.1以上。而通過程式碼檢視版本為3.1.44。

>>> import reportlab
>>> print reportlab.Version
3.1.44
>>> 
        檢視了很多資料都沒有解決該問題,其中最典型的是將pisa安裝目錄下,sx\pisa3\pisa_util.py檔案中程式碼修改:

if not (reportlab.Version[0] == "2" and reportlab.Version[2] >= "1"):
    raise ImportError("Reportlab Version 2.1+ is needed!")

REPORTLAB22 = (reportlab.Version[0] == "2" and reportlab.Version[2] >= "2")
        修改後的程式碼如下:
if not (reportlab.Version[:3] >="2.1"):
    raise ImportError("Reportlab Version 2.1+ is needed!")

REPORTLAB22 = (reportlab.Version[:3] >="2.1")

        但仍然不能解決該問題,這就導致了我無法驗證該程式碼並實現後面的HTML轉換為PDF的功能。參看了很多國外的資料:
        xhtml2pdf ImportError - Django 來自stackoverflow
        https://github.com/stephenmcd/cartridge/issues/174
        https://groups.google.com/forum/#!topic/xhtml2pdf/mihS51DtZkU
        http://linux.m2osw.com/xhtml2pdf-generating-error-under-1404

三. 總結

        最後簡單總結下吧!文章主要想實現從CSDN下載HTML靜態網頁形式的文章,再通過Python第三方庫實現轉換成PDF格式的備份文章功能,但由於Pisa無法匯入最終失敗。你可能非常失望,我也很遺憾。但仍然能從文章中學到一些東西,包括:
        1.如何通過Python獲取403禁止的內容,寫訊息頭模仿登入,採用geturl和openurl兩種方法實現;
        2.如何配置PIP,它能讓我們更方便的安裝第三方庫,讓你瞭解些配置過程;
        3.讓你瞭解了HTML轉PDF的一些思想。

        最後推薦下我以前關於Python的爬蟲文章,可能會給你提供些想法,雖然比那些開源的軟體差很多,但這方面的文章和資源還是比較少的,哪怕給你一點靈感就好。

        [Python學習] 專題一.函式的基礎知識
        [Python學習] 專題二.條件語句和迴圈語句的基礎知識
        [Python學習] 專題三.字串的基礎知識
        [Python學習] 簡單網路爬蟲抓取部落格文章及思想介紹
        [python學習] 簡單爬取維基百科程式語言訊息盒
        [python學習] 簡單爬取圖片網站相簿中圖片
        [python知識] 爬蟲知識之BeautifulSoup庫安裝及簡單介紹
        [python+nltk] 自然語言處理簡單介紹和NLTK壞境配置及入門知識(一)

        如果你有“Reportlab Version 2.1+ is needed!”好的解決方案可告知我,小弟我感激不盡。潛心學習,研究這方面的功能,最好不是呼叫第三方庫,為自己加油。
        最後希望文章對你有所幫助,如果有不足之處或錯誤的地方,還請海涵~

        (By:Eastmount 2015-5-17 凌晨3點   http://blog.csdn.net/eastmount/

相關文章