爬蟲——爬取百度貼吧每一個帖子裏面的圖片

如今咱們用正則來作一個簡單的爬蟲,咱們嘗試爬取某個百度貼吧裏面的全部帖子,而且將這個帖子裏首頁每一個樓層發佈的圖片下載到本地。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)
相關文章
相關標籤/搜索