01_爬蟲基礎知識回顧

技術選型,爬蟲能作什麼?

一、Scrapy VS requests+beautifulsoup

  • requests和beautifulsoup都是庫,Scrapy是框架。
  • scrapy框架能夠加入requests和beautifulsoup。
  • scrapy是基於twisted,性能是最大的優點。
  • scrapy方便擴展,提供了不少內置的功能。
  • scrapy內置的css和xpath selector很是方便,beautifulsoup最大的缺點就是慢。

2、爬蟲能作什麼?

  • 搜索引擎(百度、google、垂直領域搜索引擎)。
  • 推薦引擎(今日頭條、一點資訊)。
  • 機器學習的數據樣本。
  • 數據分析(如金融數據分析)、輿情分析。

正則表達式

  • 貪婪模式:正則表達式一把趨向於最大長度的匹配,也就是所謂的貪婪匹配。
  • 非貪婪匹配:就是匹配到結果就好,較少的匹配字符。
  • 默認是貪婪模式,在兩次後面直接加上一個問號就是非貪婪模式。

一、特殊字符(原始字符串'booby123')

  • ^ : ^b 以b開頭的字符串css

  • .   : 匹配任意字符串node

  • *  : 任意長度(次數),≥0python

  • () : 要取出的信息就用括號括起來正則表達式

  • ? : 非貪婪模式(從左邊開始匹配),儘量少的匹配所搜索的字符串 '.*?(b.*?b).*'----從左至右第一個b和的二個b之間的內容(包含b)算法

  • +:+ 前面的字符至少出現一次數據庫

  • {} : 前面字符出現的次數app

  • +: 出現至少一次框架

  • {2} :限定字符出現次數,2次機器學習

  • {2,5}: 出現2-5次之間,後者需大於前者scrapy

  • | :或」的關係,例如:「z|food」能匹配「z」或「food」(此處請謹慎)。「[z|f]ood」則匹配「zood」或「food」或"zood"。

  • ():提取字符串裏的值,(1)「第一個字符串值」

  • []:知足中括號內任意字符就行,進入後皆無特殊含義[.*]、區間[0-9]、具體數值[123]、不等於1[^1]

  • \s:爲空格 \S非空格

  • \w:大小寫字、數字以及下劃線,等於:[A-Za-z0-9_]

  • \W:匹配下劃線在內的任何單詞字符,[^A-Za-z0-9_]

  • \w:和上一個相反

  • [\u4E00-\u9FA5]:匹配全部中文

  • \d :匹配數字

  • \D:匹配全部非數字

二、正則表達式的運用

①貪婪模式

line = "boooobaaaooobbbbby123"

regex_str = ".*?(b.*b).*" #貪婪模式,從右邊選擇b,.*(一個或者沒有),再到左邊最前面一個b。
match_obj = re.match(regex_str,line)
if match_obj:
    print(match_obj.group(1))#group(1)表示匹配括號裏面的第一組,因此輸出:boooobaaaooobbbbb

②非貪婪模式

line = "boooobaaaooobbbbby123"

regex_str = ".*?(b.*?b).*" #非貪婪模式,從左邊選擇b,.*(一個或者沒有),再到後面第一個b
match_obj = re.match(regex_str,line)
if match_obj:
    print(match_obj.group(1))#group(1)表示匹配括號裏面的第一組,因此輸出:boooob

③年月日正則案例

line = "XXX出生於2001年6/1"
line = "XXX出生於2001-6-1"
line = "XXX出生於2001-06-01"

line = "XXX出生於2001年6月1日"
line = "XXX出生於2001-6-1"
line = "XXX出生於2001-06-01"
line = "XXX出生於2001-06"
regex_str = ".*(\d{4}[年-]\d{1,2}([月 / -]\d{1,2}|[月 / - ]$|$))" #[月日時],知足於具體數字月、日、時就能夠
match_obj = re.match(regex_str,line)
if match_obj:
    print(match_obj.group(1))

深度優先和廣度優先原理

一、深度優先和廣度優先

  • 深度優先:遞歸算法,默認模式(A、B、D、E、I、C、F、G、H)
  • 廣度優先:層次算法,隊列實現(A、B、C、D、E、F、G、H、I)

二、深度優先過程

深度優先遍歷:對每個可能的分支路徑深刻到不能再深刻爲止,並且每一個結點只能訪問一次。二叉樹的深度優先遍歷的非遞歸的通用作法是採用棧,要特別注意的是,二叉樹的深度優先遍歷比較特殊,能夠細分爲先序遍歷、中序遍歷、後序遍歷。具體說明以下:

  • 先序(根)遍歷:對任一子樹,先訪問根,而後遍歷其左子樹,最後遍歷其右子樹。
  • 中序(根)遍歷:對任一子樹,先遍歷其左子樹,而後訪問根,最後遍歷其右子樹。
  • 後序(根)遍歷:對任一子樹,先遍歷其左子樹,而後遍歷其右子樹,最後訪問根。

DFS的Python算法描述:

def depth_tree(tree_node):
    """
    # 深度優先過程
    :param tree_node:
    :return:
    """
    if tree_node is not None:
        print(tree_node._data)
        if tree_node._left is not None:
            return depth_tree(tree_node._left)
        if tree_node._right is not None:
            return depth_tree(tree_node._right)

注:scrapy默認是經過深度優先來實現的。

三、廣度優先過程

廣度優先遍歷:又叫層次遍歷,從上往下對每一層依次訪問,在每一層中,從左往右(也能夠從右往左)訪問結點,訪問完一層就進入下一層,直到沒有結點能夠訪問爲止。廣度優先遍歷的非遞歸的通用作法是採用隊列。

BFS的算法描述:

def level_queue(root):
    """
    # 廣度優先過程
    :param root:
    :return:
    """
    if root is None:
        return
    my_queue = []
    node = root
    my_queue.append(node)
    while my_queue:
        node = my_queue.pop(0)
        print(node.elem)
        if node.lchild is not None:
            my_queue.append(node.lchild)
        if node.rchild is not None:
            my_queue.append(node.rchild)

區別
一般深度優先搜索法遍歷時不所有保留結點,遍歷完後的結點從棧中彈出刪去,這樣,通常在棧中存儲的結點數就是二叉樹的深度值,所以它佔用空間較少。因此,當搜索樹的結點較多,用其它方法易產生內存溢出時,深度優先搜索不失爲一種有效的求解方法。 但深度優先搜素算法有回溯操做(即有入棧、出棧操做),運行速度慢。

廣度優先搜索算法,通常需存儲產生的全部結點,佔用的存儲空間要比深度優先搜索大得多,所以,程序設計中,必須考慮溢出和節省內存空間的問題。但廣度優先搜索法通常無回溯操做,即入棧和出棧的操做,因此運行速度比深度優先搜索要快些。

url去重方法

一、爬蟲去重的策略

  • 將訪問過的url保存到數據庫中。
  • 將訪問過的url保存到set中,只要O(1)的代價就能夠查詢url。(可是若是有1億個url,那麼很容易爆內存
    )邏輯以下:
    • 100000000 * 2byte * 50個字符 / 1024 / 1024 / 1024 ≈ 9G
  • 使用bitmap方法,將訪問過的URL經過hash函數映射到某一位。(可是容易發生哈希衝突,,即不一樣url哈希值相同。)1億bit = 12.5MB內存
  • bloomfilter方法對bitmap進一步優化,對bitmap進行了改進.,經過多個哈希函數,,減小衝突的可能性。

完全搞清楚unicode和utf8編碼

一、字符串編碼

  • 計算機自己只能處理數字,文本轉換爲數字才能處理。計算機中8個bit做爲一個字節,因此一個字節能表示最大的數字就是255。
  • 計算機是美國人發明的,因此一個字節能夠表示因此字符了,因此ASCII(一個字節)編碼就成爲美國人的標準編碼。
  • 可是ASCII處理中文明顯是不夠的,中文不止255個漢字,因此中國製定了GB2312編碼,用兩個字節表示一個漢字。GB2312還把ASCII包含進去了,同理日文韓文等等上百個國家爲了解決這個問題都發展了一套字節的編碼,標準就愈來愈多,若是出現多種語言混合顯示就必定會出現亂碼。
  • 因而unicode出現了,將全部語言統一到一套編碼裏。
  • ASCII和unicode編碼:
    • 字母A用ASCII編碼十進制65,二進制01000001
    • 漢字"中"已超出了ASCII編碼的範圍,用unicode編碼是20013,二進制01001110 00101101
    • A用unicode編碼中只須要前面補0,二進制是 00000000 01000001
  • 亂碼問題解決了,可是若是內容全是英文,unicode編碼比ASCII須要多一倍的存儲空間,同時若是傳輸須要多一倍的傳輸。
  • 因此出現了可變長的編碼「utf-8」,把英文變長一個字節,漢字3個字節。特別生僻的變成4-6字節。若是傳輸大量的英文,utf-8做用就很明顯。

二、Python3的默認採用Unicode編碼

  • decode 的方法是將bytes類型轉換爲str類型(解碼)
  • encode的方法是將str類型轉換爲bytes類型(編碼)
stingc = "我愛python"
print(stingc.encode('utf-8'))#encode的方法是將str類型轉換爲bytes類型

string = stingc.encode('utf-8')
print(string.decode('utf-8'))#encode的方法是將str類型轉換爲bytes類型(編碼)
相關文章
相關標籤/搜索