爬蟲理論知識

什么是爬蟲

  • 爬取網(wǎng)頁數(shù)據(jù)的程序 它是一門工具

網(wǎng)頁特征

  • 每個網(wǎng)頁都有不同的url(統(tǒng)一資源定位符)
  • 網(wǎng)頁都由HTML語言構(gòu)成
  • 都用HTTP/HTTPS協(xié)議傳輸

爬蟲怎么爬取網(wǎng)頁

  • 定位你要的url地址
  • 然后把網(wǎng)頁地址下載下來
  • 提取有用的數(shù)據(jù),如果有 有用的URL,那繼續(xù)爬

為什么用python做爬蟲

python:代碼簡單易懂,并且第三方的庫也有很多,python自帶的urllib網(wǎng)絡(luò)呢請求模塊,requests網(wǎng)絡(luò)請求模塊,網(wǎng)絡(luò)解析庫xpath,BeautifulSoup4,pyquery等等,還有成熟
高效穩(wěn)定的爬蟲框架scrapy(pyspider)等等,并且還支持分布式爬蟲(scrapy-redis)框架

java:是python寫爬蟲的最大的競爭對手,java的發(fā)展周期長,生態(tài)圈都比較完善,也有很多第三方庫的支持,java的代碼量比較大,開發(fā)的成本比較高,后期維護也比較繁瑣

php:php曾經(jīng)被叫做世界上最好的語言(一般用來后端的),也可以用來寫爬蟲,但是對多任務(wù)的支持不太好,爬蟲對效率要求比較高,所有一般不適用php寫爬蟲

c/c++:比較偏向于底層的語言,代碼的運行效率高,學(xué)習的門楷非常高,代碼成型比較慢.

七層協(xié)議

應(yīng)用層 表示層 會話程 傳輸層 網(wǎng)絡(luò)層 數(shù)據(jù)鏈路層 物理層

OSI七層協(xié)議的目的:實現(xiàn)不同的系統(tǒng)互聯(lián)之間的數(shù)據(jù)通訊,實現(xiàn)數(shù)據(jù)的傳輸.

應(yīng)用層:http/https
傳輸層:TCP/UDP
TCP:網(wǎng)絡(luò)傳輸協(xié)議,面向連接的,長連接,傳輸?shù)氖菙?shù)據(jù)流
,確保數(shù)據(jù)的安全性和完整性,但是數(shù)據(jù)傳輸?shù)男实?br> UDP:網(wǎng)絡(luò)傳輸協(xié)議,是非面向連接的,短連接,傳輸?shù)氖菙?shù)據(jù)包,
傳輸數(shù)據(jù)是不安全的,可能會造成數(shù)據(jù)的丟失,傳輸速度非常快

http(超文本傳輸協(xié)議,端口號是80):
實現(xiàn)從網(wǎng)絡(luò)傳輸草文本數(shù)據(jù)到本地瀏覽器的傳送協(xié)議

https(端口號是443):是http的安全版本,在http的基礎(chǔ)上添加了一個
SSL(安全套接字層)層,用于web端的安全傳送,在傳輸層
對網(wǎng)絡(luò)連接進行加密,
1.構(gòu)建了一個安全的數(shù)據(jù)傳輸通道.
2.保證網(wǎng)站的真實性和有效性

https協(xié)議需要有一個證書(CA證書):由專門的證書機構(gòu)頒發(fā)的,
也可以自己生成,但是訪問的時候會提示連接不安全

https協(xié)議需要有一個證書(CA證書):由專門的證書機構(gòu)頒發(fā)的,
也可以自己生成,但是訪問的時候會提示連接不安全

http的工作原理:

URL介紹:
URI:統(tǒng)一資源標志符
URN:統(tǒng)一資源名稱
URL:統(tǒng)一資源定位符
URI是URN和URL的父類

URL的組成部分:

https://baike.baidu.com/item/OSI/5520?fr=aladdin

https://book.qidian.com/info/1004608738

https://book.qidian.com/info/1004608738#Catalog

get:只是用于從服務(wù)器獲取數(shù)據(jù),再url連接后面
可能會跟一些查詢參數(shù)
post:向服務(wù)器端提交數(shù)據(jù),數(shù)據(jù)會放在請求體中,
     一般用于添加或者修改數(shù)據(jù)
delete:用來刪除數(shù)據(jù)
put:更新整個資源(用來做數(shù)據(jù)的更新)
patch:(更新資源)(局部數(shù)據(jù)的更新)

對比:get和post請求的區(qū)別
1.使用場景:get從服務(wù)器端獲取數(shù)據(jù),post請求向服務(wù)器端提交數(shù)據(jù)
2.安全性:get請求參數(shù)只拼接在url地址上,post請求會將參數(shù)放在
請求體中,(注意:不要誤認為只要url地址后面添加了參數(shù)就是一個get請求)
3.get請求的url是有長度限制的,post的請求體中可以添加很多字段
Cookie和Session:目的保持會話
http請求是無狀態(tài)的,每一次請求斷開后,下一次請求就
認為是一個新的請求,為了維持請求狀態(tài)就用到了Cookie
和Session

Cookie:保存在客戶端的,記錄信息確定用戶的身份
Session:保存在服務(wù)端的,同樣是記錄信息確定用戶身份

常見的請求狀態(tài)碼:

200:請求成功
3xx:重定向
    301:永久重定向
    302:臨時重定向

4xx:客戶端請求錯誤
    400:請求錯誤,服務(wù)器無法解析
    401:未授權(quán),沒有進行身份驗證
    403:服務(wù)器拒絕訪問
    404:訪問的頁面不存在
    405:請求方式不允許
    408:請求超時

5xx:服務(wù)端錯誤
    500:服務(wù)端內(nèi)部錯誤
    501:服務(wù)器暫時不具備完成請求的功能
    503:服務(wù)器不可用

urllib

request

#1.發(fā)起請求:python自帶的urllib模塊
#request:是urllib最基本的http網(wǎng)絡(luò)請求模塊

from urllib import request

#https://www.qidian.com/all

#https://www.qidian.com/all
# ?orderId=&style=1&pageSize=20
# &siteid=1&pubflag=0&hiddenField=0&page=1

#https://www.qidian.com/all
#?orderId=&style=1&pageSize=20
# &siteid=1&pubflag=0&hiddenField=0&page=2

#https://www.qidian.com/all
# ?orderId=&style=1&pageSize=20
# &siteid=1&pubflag=0&hiddenField=0&page=3

#發(fā)起請求

"""
url:設(shè)置目標url

data=None:默認為None,表示發(fā)起的是一個get請求,
        反之,不為None,表示發(fā)起的是一個post請求
        
timeout: 設(shè)置請求的超時時間(s)

cafile=None, 設(shè)置證書文件(一般不用)
capath=None, 設(shè)置證書文件路徑(一般不用)

context=None, 一般設(shè)置為一個ssl的對象
(ssl._create_unverified_context()),
忽略未認證的CA證書(如果出現(xiàn)了ssl證書錯誤)
"""

url = 'https://www.qidian.com/all?orderId=&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=0&page=1'
#如果請求需要添加請求頭,urlopen并沒有headers參數(shù)來設(shè)置請求頭
"""
url:設(shè)置目標url 
data=None,:默認為None,表示發(fā)起的是一個get請求,
        反之,不為None,表示發(fā)起的是一個post請求
headers={}:設(shè)置請求頭,傳遞一個字段類型的參數(shù)
"""
req_header = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
}
#根據(jù)url構(gòu)建一個請求對象
req = request.Request(url=url,headers=req_header)
#使用urlopen方法faqi請求,獲得響應(yīng)結(jié)果
response = request.urlopen(req,timeout=20)
# response = request.urlopen(url=url,timeout=20)
#從響應(yīng)結(jié)果中獲取相關(guān)數(shù)據(jù)
# print(response.read())
html = response.read().decode('utf-8')
print(len(html))
"""
文件讀寫模式:
r:打開一個文件,只有可讀權(quán)限  rb:   r+:  rb+
w:打開一個文件,有寫入的權(quán)限  wb:   w+:  wb+
a:打開一個文件,有追加權(quán)限    ab:   a+:  ab+:
"""
with open('quanshu.html','w') as file:
    file.write(html)

#獲取響應(yīng)的狀態(tài)碼
code = response.status
print(code)
#獲取響應(yīng)的響應(yīng)頭
response_headers = response.getheaders()
print(response_headers)
#獲取某一個響應(yīng)頭參數(shù)
server = response.getheader('Server')
print(server)
#獲取當前請求的url地址
current_url = response.url
print(current_url)
#獲取請求的reason(如果成功返回的是OK)
reason = response.reason
print(reason)
#注意:response.read(),只可以讀取一次

#https://www.baidu.com/s?wd=新年愿望

error

# error模塊:在我們請求過程中,可能因為服務(wù)器錯誤,弱網(wǎng)環(huán)境...

# 造成請求失敗,這時我們需要對這些錯誤進行異常處理,不然會造成代碼崩潰

from urllib import request,error

'''

error.URLError:

產(chǎn)生的原因主要有:

    沒有網(wǎng)絡(luò)連接

    服務(wù)器連接失敗

    找不到指定的服務(wù)器

有一個reason屬性:返回錯誤的原因

'''

'''

error.HTTPError

    HTTP請求錯誤,比如未認證,頁面不存在

    code:請求的狀態(tài)碼

    reason:返回錯誤的原因

    headers:返回響應(yīng)頭部

'''

import ssl



context = ssl._create_unverified_context()



# url = 'https://www.baidu.com/12345.htm'

url = 'https://www.qidian.com/all/nsacnscn.htm'



try:

    response = request.urlopen(url,timeout=0.01,context=context)

    print(response.status)

except error.HTTPError as err:

    print('HTTPError')

    print(err.code)

    print(err.reason)

    print(err.headers)

except error.URLError as err:

    print('URLError',err.reason)

parse

#parse:可以對url進行拆分,組合,編碼,解碼,拼接
from urllib import parse

#parse.urlencode():將字典類型的參數(shù)轉(zhuǎn)為url編碼格式
form_data ={
    'first': 'false',
    'pn': 2,
    'kd': '后端',
}
#get請求直接使用urlencode將參數(shù)轉(zhuǎn)為url編碼格式
form_data1 = parse.urlencode(form_data)
print(form_data1)
#post請求urlencode將參數(shù)轉(zhuǎn)為url編碼格式,然后使
# 用encode方法將字符串轉(zhuǎn)為bytes類型
form_data2 = parse.urlencode(form_data).encode('utf-8')
print(form_data2)

# parse.parse_qs():將url編碼格式的字符串轉(zhuǎn)化為字典類型
#注意key對應(yīng)的value是一個list
parmas = parse.parse_qs(form_data1)
print(parmas)

#parse.quote()將中文字符轉(zhuǎn)為url編碼的字符
key = '我的國'
result = parse.quote(key)
print(result)

#parse.unquote()將url編碼的字符轉(zhuǎn)換為中文字符
unquote_result = parse.unquote(result)
print(unquote_result)

#將不完整的url參照基類url,拼接完整
base_url = 'http://www.qidian.com/book/123456.html'
sub_url = '12345789.html'
full_url = parse.urljoin(base_url,sub_url)
print(full_url)

#parse.urlparse():將url進行拆分
base_url = 'http://www.qidian.com/book/123456.html'
result = parse.urlparse(base_url)
"""
ParseResult(
 scheme='http',:協(xié)議
 netloc='www.qidian.com', ip或域
 path='/book/123456.html', 路徑
 params='', 參數(shù)
 query='', 查詢參數(shù)(?后面拼接的參數(shù))
 fragment='' : 錨點
 )

"""
print(result)
print(result.scheme)
#parse.urlunparse():將url的各個部分合并為一個完整的url
#scheme, netloc, url, params, query, fragment
url_datas = ('https','www.baidu.com','book','','wd=xxx','1234')
full_url = parse.urlunparse(url_datas)
print(full_url)

正則表達式

#正則的規(guī)則:

#單字符匹配

"""

. 除換行符之外的任意字符

\d 表示數(shù)字

\D 匹配非數(shù)字

\w 匹配單詞字符[a-z,A-Z,0-9]

\W 匹配非單詞字符

\s 匹配空白字符,空格,\n \t ...

\S 匹配非空白字符

^ 匹配以...開頭

$ 匹配以...結(jié)尾

[0-9] => \d 匹配0-9

"""



#多字符匹配(貪婪匹配)

"""

* 匹配*前面的字符任意次數(shù)

+ 匹配+前面的字符至少1次

? 匹配?前面的字符0~1次

{n,m} 匹配{n,m}前面的字符n~m次

"""



#多字符匹配(非貪婪匹配)

"""

*?

+?

??

"""



#其他

"""

() 分組

| 邏輯或

\ 轉(zhuǎn)義字符

"""



#re模塊下的方法

import re



#re.compile():構(gòu)建正則表達式對象

#re.match():從起始位置開始匹配,單次匹配,匹配到

#結(jié)果立即返回,反之,返回None

str = 'abcdebfga'

pattern = re.compile('b|e')





result = re.match(pattern,str)

if result:

    print(result.group())



# re.search():在整個字符串中進行匹配,單次匹配,匹配到結(jié)果

# 立即返回,反之,返回None

result = re.search(pattern,str)

print(result.group())



# re.findall():匹配出整個字符串中,所有符合正則規(guī)則的結(jié)果

# 返回的是一個列表(list)

result = re.findall(pattern,str)

print(result)



# re.finditer():匹配出整個字符串中所有符合正則規(guī)則的結(jié)果,

# 返回的是一個可迭代對象

result = re.finditer(pattern,str)

print(type(result),result)

for i in result:

    print(i,type(i))

    print(i.group())



# re.sub():根據(jù)正則表達式進行字符串替換

new_str = re.sub(pattern,'h',str)

print(new_str)



#re.split():根據(jù)正則表達式進行分割,得到的是一個list



result = re.split(pattern,str)

print(result)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是爬蟲? 就是一段自動抓取互聯(lián)網(wǎng)數(shù)據(jù)的程序或腳本 網(wǎng)頁的三大特性 1.每個網(wǎng)頁都有自己唯一的URL地址(統(tǒng)一資...
    bda1a329d33d閱讀 537評論 0 0
  • 爬蟲: 平臺或者機構(gòu)不能夠提供我們需要的數(shù)據(jù),這時就需要爬蟲工程師,根據(jù)需求從互聯(lián)網(wǎng)上抓取數(shù)據(jù)? 什么是爬蟲? 就...
    Stranger_I閱讀 381評論 0 1
  • HTTP基本原理 URI、URL、URN(Uninform Resource) URI(Identifier):統(tǒng)...
    GHope閱讀 2,286評論 2 26
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,665評論 1 32
  • 小小說是一種頗受讀者歡迎的文學(xué)體裁,字數(shù)在1000字到3000字之間,篇幅短小,而又寓意深刻,可謂“尺水興波瀾”。...
    上官飛鴻閱讀 2,390評論 33 28

友情鏈接更多精彩內(nèi)容