Python - 爬取博客園某一目錄下的隨筆 - 保存為docx


 1 #coding:utf-8
 2 import requests 
 3 from bs4 import BeautifulSoup
 4 import MySQLdb
 5 
 6 
 7 def get_html(url):
 8     '''
 9     獲取頁面HTML源碼,並返回
10     '''
11     html = requests.get(url)
12     content = html.text.encode('utf-8')
13     return content
14 
15 def get_blog_html_list(html_content):
16     global addr
17     '''
18     在HTML源碼中獲取到blog相關的值,並返回
19     '''
20     bs = BeautifulSoup(html_content,'lxml')
21     # 此處的class要加上下划線,否則會和系統內預定的class沖突
22     blog_list = bs.find_all('div', class_ = 'entrylistItem')
23     for i in range(len(blog_list)):
24         sub_dict = {}
25         sub_dict['title'] = blog_list[i].a.get_text()
26         sub_dict['link'] = blog_list[i].a.get('href')
27         sub_dict['abstract'] = blog_list[i].div.get_text()
28         insert_to_db(sub_dict)
29     return sub_dict
30 
31 def insert_to_db(dict={} ):
32     conn = MySQLdb.connect(host = 'localhost', user = 'root', passwd = '12345a', 
33                            db = 'pytest01', charset = 'utf8')
34     cur = conn.cursor()
35 
36     try:
37         cur.execute('insert into blog_details (title, link, abstract) values (%s, %s, %s)',
38                      (dict['title'], dict['link'], dict['abstract']))
39     except MySQLdb.Error, e:
40         pass
41     conn.commit()
42     cur.close()
43     conn.close()
 1 #coding:utf-8
 2 import urllib
 3 import requests
 4 from bs4 import BeautifulSoup
 5 import MySQLdb
 6 import Crawler.get_file
 7 from docx import Document
 8 import time
 9 import docx.image   # 超鏈接圖片拋出的異常在docx.image中
10 
11 index = '0'
12 
13 def get_blog_pic(pic_url, index):
14     print 'download picture'
15     '''
16     下載指定URL的圖片,並且以index命名保存到temp_pic 文件夾內
17     '''
18     path = 'D:\\workspace_Java\\cnBlogCrawler\\temp_pic\\' + index + '.png' 
19     try:
20         pic = urllib.urlretrieve(pic_url, path)
21     except AttributeError,e:
22         path = r'C:\Users\Lisen\Desktop\error.jpg'
23         print 'download picture error, the link is ' + pic_url
24         pass
25     finally:
26         return path
27     
28 def get_blog_body(url, title):
29     print 'download blog'
30     print title, time.strftime('%Y-%m-%d %H:%M:%S')
31     file_path = 'D:\\workspace_Java\\cnBlogCrawler\\temp_doc\\' + title + '.docx'
32     header = {'Accept':'text/html,application/xhtml+xml,application/xml',
33               'Accept-Encoding':'gzip, deflate, sdch',
34               'Accept-Language':'zh-CN,zh;q=0.8',
35               'Cache-Control':'max-age=0',
36               'Connection':'keep-alive',
37               'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.75 Safari/537.36'}
38     html = requests.get(url,header).text
39     bs = BeautifulSoup(html, 'lxml')
40     print 'html ready'
41     '''
42     獲取html中blog正文部分
43     '''
44     body = bs.find_all('p')
45     '''
46     創建文檔
47     '''    
48     doc = Document()
49     for each in body:
50         # 在函數中改變全局變量需要用global聲明下
51         global index
52         '''
53         如果p節點有子節點a的話,就說明其中是帶着圖片的鏈接或者是文本本身就是鏈接,因此要分三種情況去爬取
54         1. 沒有子節點:直接獲取text部分
55         2. 有子節點 a, 但是該子節點沒有text部分,說明這是圖片
56         3. 有子節點a, 且該子節點有text部分,則里面是文本
57         '''
58         if each.a != None:
59             txt = each.a.get_text()
60             if txt == '':
61                 print 'pic'
62                 url = each.a.get('href')
63                 index = str(int(index) + 1)
64                 pic_name = get_blog_pic(url, index)
65                 try:
66                     doc.add_picture(pic_name)
67                 except docx.image.exceptions.UnrecognizedImageError, e:
68                     pass
69             else:
70                 print 'URL'
71                 content = each.a.get_text()
72                 paragraph = doc.add_paragraph(content)
73         else:
74             print 'txt'
75             content = each.get_text()
76             paragraph = doc.add_paragraph(content)
77     try:
78         print 'saving file'
79         doc.save(file_path)
80     except IOError,e:
81         print 'file saving error'
82         print 'error url is ' + url
83         pass
 1 import MySQLdb
 2 import Crawler.get_file
 3 import Crawler.get_blog_details
 4 import time
 5 
 6 if __name__ == '__main__':
 7 
 8     conn = MySQLdb.connect(host = 'localhost', user = 'root', passwd = '12345a', 
 9                             db = 'pytest01', charset = 'utf8')
10     cur = conn.cursor()
11     cur.execute('truncate blog_details')
12     url = r'http://www.cnblogs.com/omygod/category/460309.html'
13     print 'next parsing html'
14     html = Crawler.get_blog_details.get_html(url)
15     print 'next parsing blog address'
16     dict = Crawler.get_blog_details.get_blog_html_list(html)
17     print 'next update MySQL'
18     Crawler.get_blog_details.insert_to_db(dict)
19      
20     cur.execute('select * from blog_details')
21     lines = cur.fetchall()
22     for line in lines:
23         Crawler.get_file.get_blog_body(line[1],line[0])
24         print 'done' + time.strftime('%Y-%m-%d %H:%M:%S')
25         time.sleep(2)
26         print 'wait over'
27     cur.close()
28     conn.close()

 

 

由於博客園的原創博客都是通過隨筆的形式保存的,因此我們可以通過對某一隨筆目錄進行解析,獲取出該目錄下所有博文的標題,鏈接以及摘要,存儲到MySQL數據庫中(主要是因為可以持久記錄相關信息,后續有新博文的時候可以通過對比判斷直接下載新的博文)。然后再對每個條目進行單獨解析,將博文的內容,圖片保存到Word文檔中。

     主要用到的包有: requests, BeautifulSoup,python-docx, MySQLdb

    整個代碼分為三部分:

  1. 第一部分是get_blog_details.py,主要是獲取目錄下各個博文的詳細信息,並存到MySQL數據庫中
  2. 第二部分是get_file.py,獲取各個博文的地址等並生成Word文檔
  3. 第三部分是__init__.py, 程序開始  

    在編寫代碼過程中,有幾個地方需要注意:

  1. 若在函數中改變全局變量,需要在函數中聲明: global g_var
  2. 在用BeautifulSoup解析某個節點的class屬性是,不能直接用class否則會報錯,因為class是保留關鍵字, 要在class后加_, 如:blog_list = bs.find_all('div', class_ = 'entrylistItem')
  3. 在py文件中import其他py文件時,一要在文件目錄中添加 __init__.py 文件,二是要在導入是加上對應文件夾的名字,如:import Crawler.get_file

  現階段缺點:

  1. 程序運行速度慢,后期准備學習下多線程爬蟲
  2. Word文檔中圖片太大以至於不方便閱讀,准備用python-docx中的Inches修改
  3. 剛才跑的時候發現寫數據庫表的時候有一個地方沒注意,相同主鍵不能再次寫入,這個需要修改下 現在每次解析博文列表時都會先進行刪除數據庫的操作
  4. 沒有例外處理,程序容易崩潰 一定要添加例外處理,否則指不定程序在哪里就崩潰了。。
  5. 在爬取博文時發現有些博文內容含有表格,以及某些圖片是超鏈接形式,表格在下一版中修改,超鏈接圖片在此版中作為異常處理

  體會:

  1. 真的真的要做異常處理,否則會很痛苦

  2. 分析不全面,沒有考慮到含有表格或者其他形式

  3. 爭取做出GUI,方便處理

  4. 添加log 文檔, 方便查看出錯的地方

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM