如今咱們用正則來作一個簡單的爬蟲,咱們嘗試爬取某個百度貼吧裏面的全部帖子,而且將這個帖子裏首頁每一個樓層發佈的圖片下載到本地。html
分析:以美女吧爲例python
第一頁:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=0chrome
第二頁:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=50瀏覽器
第三頁:https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=100服務器
……ide
能夠發現,url地址中pn及其前面的部分是相同的,改變的只是pn後面的值函數
不難發現,每頁中共有50個帖子,全部pn的值是以每頁50的值遞增。url
則第page頁的pn值爲:(page - 1) * 50code
而kw=%E7%BE%8E%E5%A5%B3爲urllib.parse.urlencode{"kw":"美女"}htm
#!/usr/bin/python3# -*- coding:utf-8 -*-__author__ = 'mayi'"""用正則作一個簡單的爬蟲:嘗試爬取某個貼吧裏的全部帖子,而且將帖子裏每層樓發佈的圖片下載到本地。例:美女吧(https://tieba.baidu.com/f? + kw=%E7%BE%8E%E5%A5%B3 + &pn=50)https://tieba.baidu.com/f?kw=%E7%BE%8E%E5%A5%B3&pn=50其中: kw=%E7%BE%8E%E5%A5%B3爲urllib.parse.urlencode({"kw":"美女"}) pn爲值從0開始,每頁爲50個帖子,故: 第一頁,pn的值爲:0 第二頁,pn的值爲:50 第三頁,pn的值爲:100 ……"""import osimport reimport urllib.request# 一個爬蟲類class Spider(object): """ 一個爬蟲類 """ # 初始化 def __init__(self, name): """ 類的初始化 :param name: 百度貼吧名 :return: """ # User-Agent頭 self.header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36'} keyword = urllib.parse.urlencode({"kw":name}) self.url = "https://tieba.baidu.com/f?" + keyword + "&pn=" self.run() # 獲取帖子的最後一頁 def getLastPage(self, url): """ 獲取url帖子的尾頁的pn值 :param url: url地址 :return: pn值 """ html = self.loadPage(url) html = html.decode("utf-8") # 利用正則匹配尾頁的pn值 pattern = re.compile(r'<a href=.*?pn=(\d+).*?>尾頁</a>') try: pn = pattern.findall(html)[0] pn = int(pn) except: pn = 1 return pn # 爬蟲開始工做 def run(self): """ 爬蟲開始工做 :return: """ start_page = 1 end_page = self.getLastPage(self.url) // 50 + 1 print("該吧共" + str(end_page) + "頁") for page in range(start_page, end_page + 1): # 計算pn的值 pn = (page - 1) * 50 # 拼接成完整的url地址 full_url = self.url + str(pn) # 調用loadPage()函數,下載full_url的頁面內容 html = self.loadPage(full_url) # 調用screenPage()函數,篩選下載的頁面內容 item_list = self.screenPage(html) print("正在下載第" + str(page) + "頁,共" + str(len(item_list)) + "個帖子") # 調用loadImage()函數,下載帖子裏首頁的圖片 self.loadImage(item_list) # 下載網頁內容 def loadPage(self, url): """ 下載url的頁面內容 :param url: 需下載頁碼的url地址 :return: 頁面內容 """ # url 連同 headers,一塊兒構造Request請求,這個請求將附帶 chrome 瀏覽器的User-Agent request = urllib.request.Request(url, headers = self.header) # 向服務器發送這個請求 response = urllib.request.urlopen(request) # 獲取網頁內容:bytes html = response.read() return html # 篩選內容 def screenPage(self, html): """ 篩選內容:篩選出每層樓帖子的連接 :param html: 頁面內容 :return: 需下載的圖片連接地址 """ # 轉碼:bytes轉utf-8 html = html.decode("utf-8") # 利用正則匹配每層樓帖子的連接 pattern = re.compile(r'<a href="(/p/\d+).*?>.*?</a>', re.S) item_list = pattern.findall(html) return item_list # 下載帖子裏首頁裏面的圖片 def loadImage(self, item_list): """ 下載帖子裏首頁裏面的圖片 :param item_list: 需下載圖片的帖子的ID列表 :return: None """ for id in item_list: # 根據id拼接帖子連接 link = "https://tieba.baidu.com" + id start_page = 1 end_page = self.getLastPage(link) print("正在下載帖子:" + link + " 中圖片") image_no = 0 for page in range(start_page, end_page + 1): # 拼接完整連接 full_link = link + "?pn=" + str(page) # 獲取需下載圖片的帖子的頁面內容 html = self.loadPage(full_link) # 轉碼:bytes轉utf-8 html = html.decode("utf-8") # 利用正則匹配帖子中的圖片連接 pattern = re.compile(r'<img class="BDE_Image".*?src="(.*?)".*?>', re.S) # 圖片連接列表 image_list = pattern.findall(html) for image in image_list: image_no = image_no + 1 self.writeImage(image, id[3:], image_no) print("帖子:" + full_link + " 共下載" + str(len(image_list)) + "個圖片") # 向本地磁盤中存儲圖片 def writeImage(self, url, id, image_no): """ 向本地磁盤中存儲圖片 :param url: 圖片url :param id: 帖子id:本地文件夾 :param image_no: 圖片序號 :return: """ # 判斷是否存在對應的文件夾 if not os.path.exists("image/" + id): # 若不存在,則建立 os.makedirs("image/" + id) # 圖片文件名:id + "_" + 5位圖片序號 image_no = str(image_no) file_name = "image/" + id + "/" + id + "_" + "0" * (6 - len(image_no)) + image_no + ".jpg" # 以wb方式打開文件 file = open(file_name, "wb") # 獲取圖片名爲名爲 images = self.loadPage(url) # 寫入圖片 file.write(images) # 關閉文件 file.close()# 主函數if __name__ == '__main__': # 要爬取的百度貼吧名 name = input("請輸入您要爬取的百度貼吧名:") # 建立一個爬蟲對象 mySpider = Spider(name)