python爬蟲——增量式爬蟲——queue

python隊列Queue

Queue是python標準庫中的線程安全的隊列(FIFO)實現,提供了一個使用於多線程編程的先進先出的數據結構,即隊列,用來在生產者和消費者線程之間的信息傳遞。

基本FIFO隊列

class Queue.Queue(maxsize=0)。FIFO即first in first out,先進先出。queue提供了一個基本的FIFO容器,使用方法很簡單,maxsize是個整數,指明瞭隊列中能存放的數據個數的上限。一旦達到上限,插入會導致阻塞,直到隊列中的數據被消費掉。如果maxsize小於或者等於0,隊列大小沒有限制。它是進行廣度遍歷。

import queue
test = queue.Queue()
test.put("123")
print(test.get())
test.get()

然後python會一直運行。

LIFO隊列

LIFO即Last in First Out,後進先出。與棧的類似,使用同FIFO用法類似。

如果要實現增量式爬蟲,要使用FIFO隊列

以爬百度貼吧爲例:

import requests
import lxml.html
from queue import Queue


class TiebaSpider(object):
    """
    實現下載某個貼吧指定頁碼前的內容,存儲下載內容
    """

    def __init__(self, name, pages):
        """
        初始化方法
        """
        self.tieba_name = name
        self.pages_download = pages
        self.base_url = "https://tieba.baidu.com/f?kw={}&ie=utf-8&pn={}"
        self.header = {"User-Agent": "Python"}

        self.crawl_queue = Queue()
        self.crawl_queue.put(UrlType(0, "https://tieba.baidu.com/f?kw=lol&ie=utf-8&pn=0"))

    def make_url_list(self):
        """
        獲取待下載的url列表
        :return:返回生成的url列表
        """
        url_lists = []
        for i in range(self.pages_download):
            download_url = self.base_url.format(self.tieba_name, i * 50)
            url_lists.append(download_url)
        return url_lists

    # 注意maybe static 警告,怎麼消除警告?
    def save_url(self, content, file_name):
        """
        將指定內容進行存儲
        :param content:要存儲的內容,這裏傳入的參數要求是二進制
        :param file_name:文件名
        :return:無
        """
        with open(file_name, 'wb') as f:
            f.write(content)

    def download_url(self, url_str):
        """
        下載指定url處的內容
        :param url_str: 要下載的地址
        :return: 返回下載的結果
        """
        response = requests.get(url_str, headers=self.header)
        return response.text  # content是二進制數據

    def run(self):
        """
        主業務邏輯,使用run後期可以改造成多線程爬蟲
        :return:
        """
        while not self.crawl_queue.empty():
            url_type = self.crawl_queue.get()
            # 廣度優先遍歷的訪問自身
            print("正在下載", url_type.compelete_url())
            result_text = self.download_url(url_type.compelete_url())
            parse_result = lxml.html.fromstring(result_text)

            # 廣度優先遍歷的訪問鄰居
            if url_type.url_type == 1 or url_type.url_type == 0:
                result_elements = parse_result.cssselect("ul#thread_list > li.j_thread_list")
                next_element = parse_result.cssselect("div.thread_list_bottom a.next")[0]
                url_str_next = next_element.xpath(".//@href")[0]
                self.crawl_queue.put(UrlType(1, url_str_next))
                # print("next page is :",url_str_next)
                # print("*" * 50)

                for result_element in result_elements:
                    result_thread = result_element.cssselect("div.threadlist_title > a.j_th_tit")[0]
                    print(result_thread.text)
                    url_str_detail = result_thread.xpath(".//@href")[0]
                    self.crawl_queue.put(UrlType(2, url_str_detail))
                    print(url_str_detail)
            else:
                pass


class UrlType(object):
    """
    URL類型對象,用來存放網址類型
    """

    def __init__(self, url_type, url_str):
        """
        初始化函數
        :param url_type: url類型 1:下一頁 2:詳情頁
        :param url_str: url字符串
        """
        self.url_type = url_type
        self.url_str = url_str

    def compelete_url(self):
        """
        根據url_type類型返回完整的url
        :return:
        """
        if self.url_type == 1:
            return "https:" + self.url_str

        if self.url_type == 2:
            return "https://tieba.baidu.com" + self.url_str

        return self.url_str


tieba_spider = TiebaSpider('lol', 2)
tieba_spider.run()

然後就會一直進行爬取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章