天天看點

爬蟲筆記(一)

1 字元串和二進制之間的互相轉換

字元串轉化為二進制:encode() 預設為utf8,若為gbk需要注明

二進制轉化為字元串:decode() 預設為utf8,若為gbk需要注明

2 url規範:

隻能由特定字元組成,字母、數字、下劃線,如果出現其他字元(中文、空格等)就要對其進行編碼

3 urllib.response

read() 讀取相應的内容,内容是位元組類型

geturl() 讀取請求的url

getheaders() 讀取頭部資訊,清單中元素有元組

getcode() 擷取狀态碼

readlines() 按行讀取,傳回清單,内容為位元組類型

4 urllib.parse

quote() url編碼函數,将中文進行轉化為%XXX

unquote() url解碼函數,将%XXX轉化為指定字元

urlencode() 給一個字典,将字典拼接為query_string,并且實作了編碼

5 UA(user agent)使用者代理

是Http協定中的一部分,屬于頭域的組成部分,User Agent也簡稱UA。

它是一個特殊字元串頭,是一種向通路網站提供你所使用的浏覽器類型及版本、作業系統及版本、浏覽器核心、等資訊的辨別。

通過這個辨別,使用者所通路的網站可以顯示不同的排版進而為使用者提供更好的體驗或者進行資訊統計;

例如用手機通路谷歌和電腦通路是不一樣的,這些是谷歌根據通路者的UA來判斷的。UA可以進行僞裝。

6 建構請求頭部資訊(反爬蟲第一步)

僞裝自己的UA.讓伺服器認為是浏覽器在上網

建構請求對象:urllib.request.Request(參數需要提供url和僞裝UA後的請求)

7 Ajax(Asynchronous Javascript And XML)

一種建立互動式網頁應用的網頁開發技術,用于建立快速動态網頁的技術

8 URLError\HTTPError異常處理 try-except

URLError:

(1):沒有網

(2):伺服器連接配接失敗

(3):找不到指定的伺服器

HTTPError:

是URLError的子類

注:兩個同時捕獲的時候,需要将子類錯誤放在前面

9 Handler處理器、自定義Opener

urlopen() 給定一個url,發送請求,擷取響應

Request() 定制請求頭,建立請求對象

進階功能 使用代理,使用cookie

10 代理:

生活中的代理:微商、代駕

程式中的代理

正向代理 順着請求的方向去進行的代理,替用戶端去請求目标伺服器位址(爬蟲關注)擷取資料

反向代理 代理目标伺服器提供資料

配置:

浏覽器配置:設定-進階-系統-打開代理設定-連接配接-區域網路設定-代理伺服器--輸入ip和端口号

代碼配置:handler = urllib.request.ProxyHandler({'http': '123.163.97.59:9999'})

opener = urllib.request.build_opener(handler)

後續都使用opener.open方法去發送請求

11 cookie

cookie是什麼?

http協定,無狀态

網站登入時候的問題,用來記錄使用者身份的

模拟登陸

12 cookie登入

# 建立一個cookiejar對象

cj = http.cookiejar.CookieJar()

# 通過cookiejar建立一個handler

handler = urllib.request.HTTPCookieProcessor(cj)

# 根據handler建立一個opener

opener = urllib.request.build_opener(handler)

再往下所有操作都是用opener.open方法去發送請求,因為這裡帶着cookie過去了

13 正規表達式解析

為什麼引入正規表達式?

用來比對一類具有相同規則的字元串(包含正則比對和正則替換)

規則

單字元:

. :除換行以外所有字元

[]:[a-w]比對集合中任意一個字元

\d:數字[0-9]

\D:非數字

\w:數字、字母、下劃線、中文

\W:非w

\S:非空白字元

\s:所有的空白字元

數量修飾:

*:任意多次 >=0

+: 至少一次 >=1

?: 可有可無 0次或1次

{m}:固定m次

{m,n}:m-n次

邊界:

\b

\B

$:以某某結尾

^:以某某開頭

分組:

() 視為一個整體(ab){3}

() 子模式\組模式 \1 \2

貪婪模式

.*? .+?(加個?反貪婪)

re.I: 忽略大小寫

re,M:多行比對

re.S:單行比對

match\search\findall:從開頭開始\從任意位置開始\比對所有

re.sub(正規表達式,替換内容,字元串)

http://www.yikexun.cn/

需求:

爬取指定頁面的标題和内容

儲存到html檔案中,标題用h1,内容使用p即可

14 bs4

BeautifulSoup

需要将pip源設定為國内源,阿裡源、豆瓣源、網易源等

windows

(1)打開檔案資料總管

(2)位址欄上面輸入%appdata%

(3)在這裡面建立一個檔案夾 pip

(4)在檔案夾裡面建立一個檔案夾 pip.ini

寫如下内容

[global]

timeout = 6000

index-url = https://mirrors.aliyun.com/pypi/simple/

trusted-host = mirrors.aliyun.com

依賴庫bs4,lxml

簡單使用:

說明:選擇器,jquery

from bs4 import BeautifulSoup

使用方式:可以将一個html文檔,轉化為指定的對象,然後通過對象的方法或者屬性去查找指定的内容

(1)轉化為本地檔案:

soup = BeautifulSoup(open('本地檔案'),'lxml')

(2)轉化為網絡檔案:

soup = BeautifulSoup('字元串類型或者位元組類型','lxml')

(1)根據标簽名查找

soup.a 隻能找到第一個符合要求的标簽(a代表連接配接)

(2)擷取屬性

soup.a.attrs 擷取所有屬性和值,傳回一個字典

soup.a.attrs['href'] 擷取href屬性 簡寫為soup.a['href']

(3)擷取内容

soup.a.text

soup.a.string

soup.a.get_text

若标簽裡還有标簽,string結果為none,其他兩個可以擷取内容

(4)find

soup.find('a') 找到第一個符合條件的a

soup.find('a', title='qing')

soup.find('a', id='feng')

soup.find('a', class_='du')(class為關鍵字,需加下劃線)

find方法不僅soup可以調用,普通的div對象也能調用,會去指定的div裡面去查找符合要求的節點

find找到第一個對象

(5)find_all

soup.find_all('a')

soup.find_all(['a', 'b'])

soup.find_all('a', limit=2) 限制前兩個

(6)select(得到的是一個清單)

根據選擇器選擇指定的内容、

常見的選擇器:标簽選擇器、類選擇器、id選擇器、組合選擇器、層級選擇器、僞類選擇器、屬性選擇器

标簽選擇器 a

類選擇器 .dudu

id選擇器 #lala

組合選擇器 a, .dudu, #lala, .meme

層級選擇器 div .dudu #lala .meme .xixi 下面好多級

僞類選擇器 div > p > a >.lala 隻能是下面一級

屬性選擇器 input[name='lala']

select選擇器傳回的永遠是清單,需要通過下标提取指定的對象,然後擷取屬性和節點

該方法也可以通過普通對象調用,找到都是這個對象下面符合要求的所有節點

15 xpath

pip install lxml

xml 可擴充标記語言,是用來存儲和傳輸資料使用的。

和html的不同的主要有兩點:

(1)html用來顯示資料,xml是用來傳輸資料

(2)html标簽是固定的,xml标簽是自定義的

xpath用來在xml中查找指定的元素,它是一種路徑表達式

//: 不考慮位置的查找

./: 從目前節點開始往下查找

../: 從目前節點的父節點查找

@: 選擇屬性

執行個體:

/bookstore/book 選擇根節點bookstore下面所有直接子節點book

//book 選取所有book

bookstore//book 查找bookstores下面所有的book

/bookstore/book[1] bookstore下面的第一個book

安裝xpath插件

啟動和關閉插件 ctrl + shift + x

屬性定位

//input[@id="kw"]

//input[@class="btn self-btn bg s_btn"]

層級定位

索引定位(索引從1開始)

//div[@id="head"]/div/div[2]/a[@class="toindex"]

//div//a[@class="toindex"] 雙斜杠代表下面所有的a節點,不管位置

邏輯運算

//input[@name="wd" and @class="s_ipt"]

模糊比對

contains

//input[contains(@class, "s_i")] 所有的input,有class屬性,并且屬性中帶有s_i的節點

//input[contains(text(), "測試")]

starts-with

//input[starts-with(@class, "s_i")] 所有的input,有class屬性,并且屬性中以s開頭的節點

取文本

//div[@id="u_sp"]/a[5]/text() 擷取節點内容

//div[@id="u_sp"]//text() 擷取節點裡面不帶标簽的所有内容

直接将所有内容拼接起來傳回給你

ret = tree.xpath('//div[@class="song"]')

string = ret[0].xpath('string(.)')

print(string.replace('\n', '').replace('\t', ''))

取屬性

//div[@id="u_sp"]/a[5]/@href

代碼中使用xpath

from lxml import etree

兩種方式使用:将html文檔變成一個對象,然後調用對象的方法去查找指定的節點

(1)本地檔案

tree = etree.parse(檔案名)

(2)網絡檔案

tree = etree.HTML(網頁字元串)