1. 程式人生 > >【爬蟲入門】抓取糗事百科的段子1.0

【爬蟲入門】抓取糗事百科的段子1.0

爬取糗事百科資訊

注意:爬取任何一個網站,首先要確定的就是這個網站是靜態網站還是動態網站。其次看看這個GET請求是否攜帶了特殊的引數。最後需要留意請求頭中的Cookie資訊。

class QSBKSpider(object):
    """
    爬蟲類
    """

    def __init__(self):
        # 將各個頁面通用的路徑,不變的路徑宣告為屬性,呼叫方便,直接在這個屬性後面拼接頁碼
        self.base_url = "https://www.qiushibaike.com/hot/page/"
        # 初始化請求頭,偽造瀏覽器請求頭中的User-Agent欄位值,如果不修改這個欄位值,有一個預設的值:User-Agent:python-3.7 XXX。
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
        }
        #例項化工具類DataTool的物件
        self.tool=DataTool()

    def get_list_html(self, page_num):
        """
        獲取每一個列表頁的html網頁原始碼(這個獲取的原始碼就是"右鍵-網頁原始碼")中的內容
        page_num:表示將要請求的頁面的頁碼
        :return:
        """
        # 構造每一頁的url地址
        page_url = self.base_url + str(page_num)
        # 向page_url傳送GET請求,開始獲取當前頁page_num的網頁原始碼
        # 先構造Request請求物件
        request = Request(page_url, headers=self.headers)
        try:
            response = urlopen(request)
        except Exception as e:
            print(page_url + "請求失敗,原因是" + e)
            return None
        else:
            # try語句中的請求沒有出現異常,就會執行else語句,如果出現異常了就不會執行else語句了。
            # print(response)
            return response.read().decode()

    def parse_list_html(self, html):
        """
        解析上一個函式請求的html原始碼
        :param html: 列表頁的網頁原始碼
        :return:
        """
        if html:
            # 使用正則表示式解析網頁原始碼
            # 寫正則注意事項:
            # 1.儘量找到要匹配的零散的資料所在的標籤,而且這個標籤必須和這些零散的資料一樣能夠迴圈。因為findall()函式在迴圈匹配資料的時候,是按照整個正則表示式規則迴圈匹配的。
            # 2.在參考網頁中"審查元素"來設定正則匹配規則的時候,一定要確認是否和"網頁原始碼"中的標籤順序、屬性順序等保持一致,如果不一致的話,必須參考"網頁原始碼"來設定正則匹配規則。因為"審查元素"中的Html程式碼是經過Js渲染之後的原始碼。
            pattern = re.compile(
                r'<div class="article block.*?>.*?<div class="author clearfix">.*?<h2>(.*?)</h2>.*?<div class="articleGender.*?">(.*?)</div>.*?<div class="content">.*?<span>(.*?)</span>.*?<div class="stats">.*?<i class="number">(.*?)</i>.*?<i class="number">(.*?)</i>',
                re.S)
            results_list = re.findall(pattern, html)
            for data in results_list:
                new_data=self.tool.process_tuple_data(data)
                print(new_data)
            pass
        else:
            print("html原始碼為None")
import sqlite3, re
from urllib.request import Request, urlopen


class DataTool(object):
    """
    工具類:對提取的元祖中的資料,進行整理,刪除無效的字元(\n,<br/>)
    """
    # 定義刪除\n字元的正則表示式
    pattern_n = re.compile(r'\n', re.S)
    # 定義刪除<br/>字元的正則表示式
    pattern_br = re.compile(r'<br/>', re.S)

    def process_tuple_data(self, orgin_tuple_data):
        """
        用於對提取的原始元祖進行資料處理的函式
        :param orgin_tuple_data: 原始資料元祖
        :return: 返回整理之後的元祖
        """
        # 需要處理的資料:使用者暱稱、段子內容
        # sub()是正則表示式中的替換資料的方法,需要將\n這個字元替換成空字元
        # 引數:1.替換規則 2.替換結果 3.要匹配的字串
        nick_name = re.sub(self.pattern_n, '', orgin_tuple_data[0])

        # 處理段子內容
        content = re.sub(self.pattern_n, '', orgin_tuple_data[2])
        content = re.sub(self.pattern_br, '', content)

        #將處理後的資料再封裝成一個元祖,返回
        data=(nick_name,orgin_tuple_data[1],content,orgin_tuple_data[3])
        return data
obj = QSBKSpider()
html = obj.get_list_html(3)
obj.parse_list_html(html)