Python3爬蟲之爬取某一路徑的所有html檔案

王世暉發表於2016-04-08
要離線下載易百教程網站中的所有關於Python的教程,需要將Python教程的首頁作為種子url:http://www.yiibai.com/python/,然後按照廣度優先(廣度優先,使用佇列;深度優先,使用棧),依次爬取每一篇關於Python的文章。為了防止同一個連結重複爬取,使用集合來限制同一個連結只處理一次。
使用正規表示式提取網頁原始碼裡邊的文章標題和文章url,獲取到了文章的url,使用Python根據url生成html檔案十分容易。


import re
import urllib.request
import urllib
from collections import deque
# 儲存檔案的字尾
SUFFIX='.html'
# 提取文章標題的正規表示式
REX_TITLE=r'<title>(.*?)</title>'
# 提取所需連結的正規表示式
REX_URL=r'/python/(.+?).html'
# 種子url,從這個url開始爬取
BASE_URL='http://www.yiibai.com/python/'


# 將獲取到的文字儲存為html檔案
def saveHtml(file_name,file_content):
#    注意windows檔案命名的禁用符,比如 /
    with open (file_name.replace('/','_')+SUFFIX,"wb") as f:
#   寫檔案用bytes而不是str,所以要轉碼
        f.write(bytes(file_content, encoding = "utf8"))
#   獲取文章標題
def getTitle(file_content):
    linkre = re.search(REX_TITLE,file_content)
    if(linkre):
        print('獲取文章標題:'+linkre.group(1))
        return linkre.group(1)
 
#   爬蟲用到的兩個資料結構,佇列和集合
queue = deque()
visited = set()
#   初始化種子連結 
queue.append(BASE_URL)
count = 0
 
while queue:
  url = queue.popleft()  # 隊首元素出隊
  visited |= {url}  # 標記為已訪問
 
  print('已經抓取: ' + str(count) + '   正在抓取 <---  ' + url)
  count += 1
  urlop = urllib.request.urlopen(url)
  # 只處理html連結
  if 'html' not in urlop.getheader('Content-Type'):
    continue
 
  # 避免程式異常中止
  try:
    data = urlop.read().decode('utf-8')
    title=getTitle(data);
    # 儲存檔案
    saveHtml(title,data)
  except:
    continue
 
  # 正規表示式提取頁面中所有連結, 並判斷是否已經訪問過, 然後加入待爬佇列
  linkre = re.compile(REX_URL)
  for sub_link in linkre.findall(data):
      sub_url=BASE_URL+sub_link+SUFFIX;
# 已經訪問過,不再處理
      if sub_url in visited:
          pass
      else:
          # 設定已訪問
          visited |= {sub_url}
          # 加入佇列
          queue.append(sub_url)
          print('加入佇列 --->  ' + sub_url)
 



相關文章