1. 程式人生 > >爬蟲不過如此(python 詳細篇)

爬蟲不過如此(python 詳細篇)

網路爬蟲(又被稱為網頁蜘蛛,網路機器人,在FOAF社群中間,更經常的稱為網頁追逐者),是一種按照一定的規則,自動地抓取全球資訊網資訊的程式或者指令碼。

爬蟲的本質就是一段自動抓取網際網路資訊的程式,從網路獲取感興趣的資訊,抓取對於我們有價值的資訊,爬蟲技術是大資料和雲端計算的基礎。

爬蟲的實現可認為是模擬瀏覽器與伺服器數據互動,偽造HTTP請求。

 

使用總覽

網頁爬取庫:

1、urllib模組的urllib.request       

#基本被取代

 

2、requests 第三方庫               

#中小型爬蟲開發

#官網:http://www.python-requests.org/en/master/

 

3、Scrapy 框架                         

#大型爬蟲開發

 

內容解析庫:

1、BeautifulSoup庫

#提取HTML和XML裡的資料   

#官網https://www.crummy.com/software/BeautifulSoup/bs4/doc/

 

2、re模組

#正則表示式,處理字串

 

檢視網站爬蟲協議

url/robots.txt

 

requests庫基本使用:

安裝: 

sudo pip3 install requests

 

使用介紹:

 1 import requests #匯入庫
 2 
 3 
 4 #get請求資料
 5 res=requests.get("http://www.baudu.com")#get請求URL
 6 # res=requests.get("http://www.baidu.com",params={"w1":"ww11","w2":"ww22"})#get帶引數請求
7 print(res.url)#獲取到訪問的URL 8 9 10 11 #post請求資料 12 res=requests.post("http://www.baudu.com")#post請求URL 13 # res=requests.get("http://www.baidu.com",data={"w1":"ww11","w2":"ww22"})#post帶引數請求 14 15 #post上傳檔案 16 #filex={"img":open('dongdd/web.py','rb')}#檔案表單 17 #filex={"img":("evil.jpg",open('dongdd/1.jpg','rb'))}#指定檔名更改為evil.jpg 18 filex={"img":("veil.txt","人的一切痛苦,\r\n本質上是對自己無能的憤怒!\r\n wowo")}#以檔案儲存字串 19 res=requests.post(urlx,files=filex) 20 21 22 23 #cookies 24 #cookie在請求頁第一次設定後是不能馬上用下列函式拿到值的,必須是請求前存在 25 26 print(res.cookies)#列印所有cookie 27 print(res.cookies["us"])#獲取單個cookie 28 29 #攜帶自定義cookie,可做當次頁面cookie比較驗證 30 coo={"cc1":"ccc01","cc2":"ccco2"} 31 res=ss.post("http://192.168.43.21:8080/login.php",cookies=coo) 32 33 #自動攜帶網站上的cookie,訪問頁面,上面程式碼設定cookie的不可被自動攜帶,必須每次手動 34 ss=requests.Session() 35 res=ss.post("http://192.168.43.21:8080/login.php") 36 res=ss.post("http://192.168.43.21:8080/cancel.php")#可做頁面1中cookie驗證 37 38 39 40 #超時 41 #預設為一直請求URL,處於停止狀態,所以必須要設定超時 42 res=requests.post("http://192.168.43.121:8080/login.php",timeout=0.2)#連線時間為:0.2s 43 #設定連線超時和讀超時:timeout=(3.05, 27) #第一個為規定連線時間,第二個為規定讀取時間 44 #永遠等待相應:timeout=None 45 46 47 #修改或新增請求頭,請求頭的必要引數可修改 48 headx={'User-Agent': 'wwwwwwwww', 'Connection': 'xxxxxxx', 'tt': '--------'} 49 res=requests.get("http://193.112.87.66/wx/file.php",headers=headx) 50 print(res.request.headers)#獲取請求頭 51 52 #其他相關引數 53 print(res.status_code)#獲取訪問狀態碼,200(系統常量:requests.codes.ok)為成功 54 print(res.raise_for_status())#請求錯誤時可以列印錯誤(4XX客戶端錯誤或5XX伺服器錯誤響應) 55 print(res.encoding)#檢視編碼 56 res.encoding="utf-8"#更改編碼 另外值:ISO-8859-1 57 print(res.headers)#以字典形式列印相應頭,HTTP標頭名稱不區分大小寫 58 print(res.headers["date"])#print(res.headers.get("DAte"))打印出相應頭時間資訊 59 print(res.text)#列印網頁原始碼 60 61 #json資料解析: 62 jsontt1=res.json()#得到json資料 63 print(jsontt1.keys())#輸出所有json可鍵名 64 print(jsontt1["key11"])#獲取單個鍵的資料 65 66 #二進位制格式資料:res.content 67 #獲取一張網路圖片並存儲實現: 68 res=requests.get("http://193.112.87.88/wx/img/0.jpg",timeout=5)#訪問得到圖片資料 69 f=open("ww.jpg","wb")#以二進位制方式開啟檔案 70 f.write(res.content)#寫入二進位制資料 71 f.close()#必須關閉檔案 72 73 #從伺服器獲取原始套接字響應,您可以訪問res.raw,必須設定:stream=True 74 #資料只能使用一次(類似檔案指標) 75 res=requests.get("http://193.112.87.88/wx/file.php",stream=True) 76 res.raw.read(10)#讀十個位元組 77 78 #另一種方式獲取網頁原始碼: 79 res=requests.get("http://193.112.87.88/wx/file.php",stream=True) 80 rxx=res.raw.read(1)#讀取一個位元組 81 f=open("www.txt","wb") 82 while rxx:#判斷是否為空 83 print(rxx) 84 f.write(rxx)#寫一個位元組 85 rxx = res.raw.read(1)#讀下一個位元組 86 f.close();#必須關閉檔案

 

re庫(正則表示式)基本使用:

安裝:

python3環境自帶

 

基本介紹:

 

1、正則表示式是獨立的語言,正則語言是共通的,比如之前寫的PHP正則裡有很多共同性

 

2、內容裡存在原子:原子是匹配單元,必須存在

 

轉義字元:如點代表所有字元所有可用\.表示點

 

.】、【\】、【?】、【^】、【$】、【*】、【+】、【}】、【{】、【[】、【]】、【|】、【(】、【)】

 

 

 

特殊符號字元:

 

【\d】所有數字,相當於[0-9]

 

【\D】所有非數字,相當於[^0-9]

 

【\w】任意一個字(a-z、A-Z、0-9、下劃線、中文字)

 

【\W】任意非字,相當於[^a-zA-Z0-9_中文字]

 

【.】(點)任意一個原子

 

【\s】所有空白(空格、tab鍵、換行),相當於[\r\t\n\f\v]

 

【\S】任意非空白

 

 

 

匹配任意一個:

 

[字元1字元2字元3]//也可為[a-zA-Z]區間//匹配任意一個

 

^】為取反,寫在中括號內開頭處,表示除了括號裡的所有字元都可以

 

【^】表示普通字元,寫在括號裡除最前面的任意位置

 

  括號裡的字元需要轉義,雖然有些不用轉義

 

 

 

3、  內容裡存在原子符:對原子的修飾補充

 

【*】修飾前面的單個原子可以出現任意次

 

【+】修飾前面的單個原子至少要出現1次

 

【?】修飾前面的單個原子只能出現0次或者1次

 

【{ n }】修飾前面的單個原子只能出現n次

 

【{a,b}】修飾前面的單個原子只能出現  [ a , b ]  次 //至少兩次用{2,  }

 

【|】修飾兩邊字串任意誰整體出現,/intelligent|diligent/

 

【^字元1】必須以字元1開始的行,r’^xceee’必須以xceee為開始,寫在表示式最前面

 

【$字元2】必須以字元2結尾的行,/\Aaa.*wo$/必須以aa開始和wo為結束,.*表示任意

 

【\A和\Z】開始和結束,用法跟上相同 ,但不是以行為結束

 

【\b】單詞邊界(空格),r’\bare\b’,匹配字串“ware are xxx”匹配到are單詞,

 

【\B】單詞邊界以外的部分

 

【()】改變優先順序,r’t(r|x)ol’,可匹配trol或者txol

 

以小變大:r’tel*’表示l可出現任意次=>r’t(el)*’表示el可出現任意次

用於取出:r’t(el)(.*)’如"xxwtelelllll"輸出:[('el', 'elllll')]

 

使用介紹:

 

 1 import re #匯入re模組
 2 
 3 #整體匹配
 4 str=r'To live is to live' #原字串,r表示原始字元,如‘\n’並不會被解釋為換行
 5 zstr=re.findall("li",str); #查詢所有,返回列表
 6 print(zstr); #列印列表 輸出:['li', 'li']
 7 
 8 #用[ ]匹配其中一個
 9 str=r'live and love' 
10 zstr=re.findall("l[io]ve",str); 
11 print(zstr); #輸出:['live', 'love']
12 
13 
14 
15 
16 #方法:compile(),生成re物件
17 str=r'aawobbxxaatabbb' #原字串
18 re_job=re.compile("a        a.*?b b",re.I|re.X)#建立re物件
19 zstr=re_job.findall(str); #使用re物件去查詢
20 print(zstr); #列印列表,輸出:['aawobb', 'aatabb']
21 
22 #第二個引數值:
23 #【re.I】不區分大小寫,r’teL’可匹配tel、Tel、TEL 等
24 #【re.M】換行後不示為同行,預設將\n換行示為以上一行為同一行,影響【^】【$】/^aa/使用有區別
25 #【re.S】修正表示式中【.】可匹配回車\n,如/a.*art/s匹配"I am \nsmart"
26 #【re.X】忽略正則表示式內容裡所寫的空白間隔,去掉空字元和# 後面的註釋
27 #【re.U】根據Unicode字符集解析字元。這個標誌影響 \w, \W, \b, \B
28 
29 #方法:match(),正則字串匹配開頭
30 str=r'xxwtelelllll' #原字串
31 zstr=re.match('xx',str); #使用re物件去查詢
32 print(zstr); #輸出物件:<re.Match object; span=(0, 2), match='xx'>,未匹配到則返回None
33 if(zstr):
34     print("匹配成功")
35 else:
36     print("匹配失敗")
37 
38 #方法:search(),正則字串匹配任意一個位置
39 str=r'wtxxelelxxllll' #原字串
40 zstr=re.search('xx',str); #使用re物件去查詢
41 print(zstr); #輸出物件:<re.Match object; span=(2, 4), match='xx'>,未匹配到則返回None
42 if(zstr):
43     print("匹配成功")
44 else:
45 print("匹配失敗")
46 
47 #方法:sub(),正則法替換字串內容
48 str=r'--x2x--xvx--' #原字串
49 zstr=re.sub('x.*?x','Python',str); #使用re物件去查詢
50 print(zstr);#輸出:--Python--Python—
51 #將re.sub換成:re.subn()則輸出次數:('--Python--Python--', 2)
52 
53 #方法:split(),正則法拆分字串內容
54 str=r'1+2-6/1|2^5' #原字串
55 zstr=re.split(r'[\^\+\*\|\/\-]',str); #使用re物件去查詢
56 print(zstr);#輸出:['1', '2', '6', '1', '2', '5']

 

BeautifulSoup庫基本使用

安裝:

   sudo pip3 install beautifulsoup4

   sudo pip3 install lxml


使用介紹:
 1 from bs4 import BeautifulSoup#匯入模組
 2 import requests #網頁訪問庫
 3 res=requests.get("http://193.112.87.88/wx/file.php")
 4 res.encoding="utf-8"
 5 
 6 be=BeautifulSoup(res.text,"lxml")#得到BeautifulSoup物件,lxml為HTML解析器,如XML解析則要用xml
 7 print(be.find_all("form"))#輸出編碼
 8 print(be.prettify())#以標準HTML格式輸出網頁原始碼
 9 
10 print(be.input)#獲取到第一個input標籤全部內容:<input name="img" type="file"/>
11 print(be.form.input)#獲取到標籤(form)下的子標籤(input)
12 print(be.form.encode("latin-1"))#自定義編碼輸出
13 print(be.input.parent.parent)#獲取input標籤的父節點的父節點
14 print(be.input.previous_sibling)#上一個兄弟節點
15 print(be.input.next_sibling)#下一個兄弟節點
16 print(be.img)#獲取到第一個img標籤內容:<img src="img/0.jpg"/>
17 picture=be.img
18 print(picture.get('src'))#獲取該屬性值(優先考慮):img/0.jpg
19 print(be.img["src"])#直接獲取屬性值
20 
21 #獲取到標籤內容值
22 print(be.title) # <title>東小東頁</title>
23 print(be.title.text) #東小東頁
24 print(be.title.string) #東小東頁
25 
26 #函式find_all()和find()使用,引數使用是相同的
27 #引數值均可使用:字串、列表、正則物件、True(任意值)
28 
29 print(be.find_all(class_="yzm",limit=2))#limit為要返回的條數
30 print(be.find_all('input')) #查詢所有標籤名為input,存入到列表
31 be.find_all(id='link2')#通過id值查詢
32 print(be.find_all(type=True))#type為true表示可以接收任意值
33 print(be.find_all(class_="yzm"))#通過class屬性查詢內容,注意class後面有下劃線
34 print(be.find_all(src=re.compile(r"img/.*?jpg")))#通過src屬性查詢
35 print(be.find_all('img')[0]["src"])# img/0.jpg
36 #--------------------------------------------------
37 import re #使用正則表示式
38 for inx in be.find_all(re.compile(r"i")):#匹配帶i字母的所有標籤名
39     print(inx.name)
40 #------------------------------------------------
41 for inx in be.find_all(["input","img"]):#列表傳遞多個需匹配標籤名
42    print(inx)
43    print(inx.get("name"))#獲取標籤name屬性值
44 #------------------------------------------------------
45 
46 #找到第一個,且只找一個
47 print(be.find(type="file"))#通過屬性查詢
48 print(be.find("input"))#通過標籤查詢
49 print(be.find("input",type="password"))#通過標籤加屬性查詢,可支援有:id、type等
50 print(be.find(text="東小東").parent)#通過text屬性查詢:<legend>東小東</legend>
51 #引數不支援name和data-*
52 print(be.find_all(attrs={"name":"yzm"}))#可用此方法解決
53 
54 
55 #擴充套件:
56 be=BeautifulSoup(open("www.txt","rb"))#直接讀取檔案內容