Python3爬蟲1
阿新 • • 發佈:2018-11-26
- 爬蟲原理:請求網站並提取資料的自動化程式
- 通用爬蟲:搜尋引擎爬蟲;聚焦爬蟲:獲取某一垂直領域的資料或者有明確的檢索需求,需要過濾掉一些無用的資訊
- HTTP協議:用於從WWW伺服器傳輸文字到本地瀏覽器的傳送協議;HTTPS協議是加密的超文字傳輸協議
- HTTP主要請求方式
- GET請求:是以實體的方式得到由請求URL所指定資源的資訊
- POST請求:用來向目的服務發出請求,並且帶上某些資訊,如果使用者輸入的資料包敏感資料,那麼使用POST為好
- PUT請求:請求伺服器儲存一個資源,通常要指定儲存的位置
- DELETE請求:請求伺服器刪除一個資源
- HEAD請求:請求獲取對應的HTTP頭資訊
- OPTIONS請求:可以獲得當前URL所支援的請求型別
- HTTP頭部資訊:HTTP頭部資訊由眾多的頭域組成,每個頭域由一個域名,冒號和域值三部分組成;F12->Network->Doc即主要請求,其中的Headers分頁即請求頭,包含請求頭部資訊
- Request Method代表的是請求方式,HTTP/1.1表示使用HTTP1.1協議標準,200OK說明請求成功
- Host頭域,指定請求資源的Intenet主機和埠號,必須表示請求URL的原始伺服器或閘道器的位置;即網址
- User_Agent頭域,裡面包含發出請求的使用者資訊,其最終由使用的瀏覽器型號,版本和作業系統的資訊。這個頭域經常用來作為反爬蟲的措施,普通爬蟲不包含User_Agent
- Accept:瀏覽器支援的內容型別
- Accept-Encoding:瀏覽器支援的語言型別
- Connection:客戶端和伺服器的連線型別,對應的欄位值有keep-alive永續性連線和close單方面管理連線
- Referer來源網址地址
- HTTP主要請求方式
- 爬蟲流程
- 網頁特徵
- 網頁都有自己唯一的URL(統一資源定位符)來進行定位
- 網頁都使用HTML (超文字標記語言)來描述頁面資訊
- 網頁都使用HTTP/HTTPS(超文字傳輸協議)協議來傳輸HTML資料
- 基本流程
- 發起請求:通過HTTP庫向目標站點發起請求,即傳送一個Request,請求可以包含額外的headers等資訊,等待伺服器響應
- 獲取響應內容:如果伺服器能正常響應,會得到一個Response,Response的內容便是所要獲取的頁面內容,型別可能有HTML,Json字串,二進位制資料(如圖片視訊)等型別
- 解析內容:得到的內容可能是:
- HTML,可以用正則表示式、網頁解析庫進行解析
- Json,可以直接轉為Json物件解析
- 二進位制資料,可以做儲存或者進一步的處理
- 儲存資料:儲存形式多樣,可以存為文字,也可以儲存至資料庫,或者儲存特定格式的檔案
- 網頁特徵
- 爬蟲與反爬蟲
- 反爬蟲機制:
- 分析使用者請求的Headers資訊,網站中應用的最多
- 驗證使用者行為,在短時間內是否頻繁訪問網站
- 動態頁面增加爬蟲難度
- 應對策略
- 構造使用者請求的Headers資訊
- 使用代理伺服器並經常切換代理伺服器
- 利用工具軟體,例如selenium+phantomJs
- 反爬蟲機制:
- 請求與響應
- 請求Request:瀏覽器傳送訊息給該網址所在的伺服器
- 主要方式有GET和POST
- URL統一資源定位符
- 請求頭部資訊包括User-Agent,Host,Cookies
- 請求時能攜帶額外的資料,即POST
- 響應Response:伺服器收到瀏覽器傳送的訊息後,能夠根據瀏覽器傳送訊息的內容,做相應處理,然後把訊息回傳給瀏覽器
- 響應狀態:200成功,301跳轉,403forbidden禁止訪問,404找不到頁面,502伺服器錯誤
- 響應頭,如內容型別,內容長度,伺服器資訊,設定Cookie(使用者行為)等
- 響應體包含最主要的請求資源的內容
- 瀏覽器收到伺服器的Response資訊後,會對資訊進行相應處理,然後展示
- 請求Request:瀏覽器傳送訊息給該網址所在的伺服器
- 資料選擇和處理
- 抓取資料型別:
- 網頁文字HTML文件,Json格式文字
- 圖片的二進位制檔案
- 視訊的二進位制檔案及其他
- 解析方式
- 直接處理
- Json解析
- 正則表示式
- BeautifulSoup
- PyQuery
- XPath
- JavaScript渲染問題
- 分析Ajax
- Selenium/WebDriver
- Splash
- PyV8/Ghost.py
- 儲存資料
- 文字
- 關係型mysql和非關係型Redis資料庫
- 二進位制檔案,如圖片,視訊
- 抓取資料型別:
- *爬蟲工具gooseeker,八爪魚等
- 爬蟲基本請求庫Urllib:Urllib是python內建的HTTP請求庫,也是python爬蟲的基礎庫
- *Urllib.request請求模組,Urllib.Error異常處理模組,Urllib.parse解析
- response=urllib.request.urlopen(url,data,timeout)->response.read().decode('')
- 前端知識:<head>包含的<meta>內有content="charset="即網頁編碼屬性
- url網址
- data訪問網站時傳送的資料包,預設null
- timeout等待時長
- decode('')解碼,把位元組流形式資料以網頁的字元格式轉化為字串
- urllib.request.urlretrieve(url,filename='*.html')直接儲存html文件
- **每次操作都會有快取,多次爬蟲必須加上清除快取的步驟urllib.request.urlcleanup()
- 搜尋引擎框中的中文會自動轉化為ASCII碼進行搜尋,所以在構造搜尋網頁url時,urllib.request.quote(keyword)將搜尋關鍵字先轉化為編碼
- POST資料傳送
- urllib.parse.urlencode({}).encode('utf-8')HTML中post方法表單中的輸入框的標籤name對應想要上傳值的字典;用encode()將字串轉化為相應編碼格式的二進位制位元組流形式->urllib.request.urlopen(url,data)中的data即urllib.parse.urlencode({}).encode('utf-8')想要上傳的位元組流資料
- encode編碼,decode解碼
- **urllib高階用法:應對反爬蟲設定
- 設定Headers
- urllib.request.urlopen(urllib.request.Request(url=url,headers={'User-Agent':''})).read().decode();urllib.request.Request()即設定請求細節,放入headers的User-Agent瀏覽器資訊
- Proxy(代理)的設定
- urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler({'http':proxy_addr})))設定全域性代理伺服器,傳入proxy_addr需要加上埠
- Timeout設定urllib.request.urlopen(url,data,timeout),設定一次請求的等待時間,超過即停止請求
- 設定Cookie:Cookie即儲存在瀏覽器中的使用者資訊,可用於繞過登入等,http是無狀態的協議,不儲存登入資訊
- import http.cookiejar
- 利用登入跳轉頁面url
- 寫data登入資訊:urllib.parse.urlencode({}).encode('utf-8')
- cjar=http.cookiejar.CookieJar()建立物件
- 建立cookie處理器和opener物件,並載入cookie設定urllib.request.install_opener(urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar)))
- urllib.request.urlopen(url,data)請求得到登入後的頁面
- 異常處理
- import urllib.error
- try:...except urllib.error.URLError|HTTPError as e:...;捕捉到URLError|HTTPError錯誤
- 設定Headers
- 爬蟲高階請求庫Request:import requests
- 特點
- Requests是用python語言基於urllib編寫的HTTP請求庫
- Requests實現HTTP請求非常簡單,更具有Python風格,操作更加人性化
- Requests庫是第三方模組,需要額外進行安裝pip install requests
- 功能
- GET和POST
- requests.get(url,headers={'User-Agent':''},cookies={},proxies={},timeout=):get請求
- requests.post(url,data={}):post請求,data傳入資料為method="post"的表單中的輸入框的name和對應輸入值
- requests.get(url).content|text:請求的位元組流|文字輸出,content.decode可解碼
- 響應與編碼:import chardet檢測字串和檔案編碼
- requests.get(url).encoding=chardet.detect(requests.get(url).content)['encoding']獲取當前get請求網頁的編碼格式,直接賦值給get請求網頁檔案的編碼
- *requests.get(url).status_code獲取當前get請求網頁的響應值
- Headers設定
- requests.get(url,headers):利用headers的User-Agent瀏覽器資訊
- Cookies設定
- 登入後介面的headers內的cookie資訊
- 傳入的cookies為字典,且先用for迴圈將cookie按;切分,以第一個等號分隔name和value
- for i in string.split(';'):name,value=i.strip().split('=',1) cookie[name]=value
- requests.get(url,cookies=)利用cookies
- 代理設定
- 上網查詢代理ip->proxies={'http':'ip:port'}
- requests.get(url,proxies={})利用ip
- 超時設定
- requests.get(url,timeout=)設定請求時間;可用r.status_code檢視頁面請求狀態
- GET和POST
- 特點
- 爬蟲解析法Beautiful Soup:是一個可以從HTML或XML檔案中查詢提取資料的Python庫,它能夠通過你喜歡的轉換器實現慣用的文件導航,查詢,修改文件的方式;效率較高上手簡單;pip install bs4;解析器:pip install lxml
- *解析器BeautifulSoup(markup,"")
- python標準庫:html.parser,python內建
- lxml HTML解析器:lxml
- lxml XML解析器:xml,唯一支援XML的解析器
- html5lib:html5lib,以瀏覽器的方式解析文件,生成HTML5格式的文件
- BS將HTML文件轉換成一個樹形結構,每個節點即python物件,物件可分為4類
- Tag:標籤<div>,<p>
- NavigableString:字元內容操作物件,表示標籤裡面的內容
- BeautifulSoup:文件物件,表示的是一個文件的全部內容
- Comment:特殊型別的NavigableString,為標籤內註釋的內容
- 使用
- from bs4 import BeautifulSoup
- 建立BS物件:讀取HTML文件或使用HTML格式字串soup=BeautifulSoup(html,"解析器")
- 利用BS物件:
- *soup.prettify()標準縮排HTML文件輸出
- 獲取標籤:soup.標籤名;若有多個同名標籤,只能獲取第一個標籤
- 獲取屬性:soup.標籤名.attrs,獲取屬性字典;soup.標籤名['屬性名']
- 獲取標籤中間的內容:soup.標籤名.string
- 如果標籤中只有一個子標籤,返回子標籤中文字內容
- 如果標籤中有多個子標籤,返回None
- 遍歷文件樹
- 子節點
- soup.標籤.contents:匹配標籤的所有子節點及其內容
- soup.標籤.children:匹配標籤的子節點列表迭代器,for i in soup.p.children
- 父節點
- soup.標籤.parent:匹配標籤的父節點及其內容
- soup.標籤.parents:匹配標籤的父節點列表迭代器
- 兄弟節點
- soup.標籤.next|previous_sibling:匹配標籤的同級前|後節點;實測不輸出
- soup.標籤.next|previous_siblings匹配標籤的同級前|後所有節點列表迭代器;最好用這個輸出兄弟節點
- 子節點
- 搜尋文件樹:
- soup.find_all(''):根據標籤名,屬性,內容查詢文件;返回列表
- soup.find_all([])多個標籤
- soup.find_all(re.compile('d+'))正則表示式查詢,整個標籤中包含d字元
- soup.find_all(id='')關鍵字引數查詢
- soup.find_all(text='')標籤中間內容匹配,得到的也是標籤的中間內容
- for i in soup.find_all('p'):print(i.find_all('a'))巢狀查詢,soup.find_all()也是BS物件
- soup.find(''):返回的匹配結果的第一個元素
- soup.find_parents()|soup.find_parent():查詢所有|一個父節點
- soup.find_next|previous_sibling(s)():查詢後|前所有|一個兄弟節點
- soup.find_(all_)next|previous():查詢後|前所有|一個節點
- soup.find_all(''):根據標籤名,屬性,內容查詢文件;返回列表
- css選擇器:返回list;css檔案即對網頁各個元素進行樣式設計,對網頁元素的多種選擇方法都能在.select('')內使用
- css語法:
- 標籤名不加修飾
- 類名前加.,id名前加#
- a,p:找到所有的a和p標籤
- a p:找到a標籤下所有的p標籤
- soup.select().get_text():獲取標籤中間的文字內容
- 操作
- soup.select('#id'):id查詢
- soup.select('.class'):class查詢
- soup.select("a[href='']"):css寫法的查詢
- css語法:
- *解析器BeautifulSoup(markup,"")
- 爬蟲解析法Xpath:Xpath原本是在可擴充套件標記語言XML中進行資料查詢的一種描述語言;對於標記語言都有非常友好的支援,如超文字標記語言HTML
- 選取節點
- nodename:選取節點的所有子節點
- /:起始為/則表示從根節點選取(且為元素的絕對路徑);bookstores/book表示bookstores元素的後代的所有book元素
- //:從匹配選擇的當前節點中選擇文件中的節點,不考慮其位置
- .:選擇當前節點
- ..:選擇當前節點的父節點
- @:選擇屬性
- 謂語:查詢某個特定的節點或者包含某個指定的值的節點,謂語被嵌在方括號中,類似索引
- /bookstores/book[1]:選取屬於bookstores子元素的第一個book元素
- /bookstores/book[last()]:選取屬於bookstores子元素的最後一個book元素
- /bookstores/book[position()<3]:選取屬於bookstores子元素的前兩個book元素
- //title[@lang]:選取所有擁有名為lang的屬性的title元素
- /bookstores/book[price>35]:選取bookstores元素中的所有book元素,且其中的price元素>35
- /bookstores/book[price>35]/title:選取bookstores元素中的所有book元素,且其中的price元素>35,下面的title元素
- 選取未知節點
- *:匹配任何元素節點
- @*:匹配任何屬性節點
- node():匹配任何型別節點
- 路徑選取
- /bookstores/*:選取bookstores元素的所有子元素
- //*:選取文件中的所有元素
- //title[@*]:選取所有帶有任何屬性的title元素
- //book/title|//book/price:選取book元素的所有title和price元素
- //book|//price:選取文件中所有的title和price元素
- /bookstores/book/title|//price:選取屬於bookstores元素的book元素的所有title元素和文件中所有的price元素
- *div是除法
- 操作
- from lxml import etree
- 初始化構造Xpath解析物件:html=etree.HTML(text),text即HTML文件
- 利用Xpath物件
- html.xpath('//p'):查詢所有p標籤
- html.xpath('//@name'):查詢所有name屬性的值
- html.xpath('//*[@name]'):查詢所有包含name 屬性的標籤
- html.xpath('//*[@name="desc"]'):)查詢所有包含name屬性,並且name屬性值為desc的標籤
- for p in html.xpath('//p'):print(p.text):查詢所有p標籤中間的文字內容,不包含子標籤
- for p2 in html.xpath('//p'):print(p2.xpath('string(.)')):查詢多個p標籤下的所有文字內容,包含子標籤中的文字內容
- html.xpath('//div/p[3]/@name'):第三個p標籤的name屬性值
- 選取節點
- 爬蟲解析法正則表示式:上手難但最全面;用規則字串來表達對字串的一種過濾邏輯;
- 操作
- import re
- re.search(pattern,string):pattern為正則表示式'',string是被檢驗的字串'';匹配到的字元和所佔位置,從0開始,左閉右開
- re.findall(pattern,string):返回所有匹配正則表示式的字串列表
- re.compile(string):返回pattern物件
- re.match(pattern,string):從string的第一個字元開始匹配,如果出錯直接返回None
- re.sub(pattern,replace,string,count):string中所有匹配的字串轉化為replace,count可以指定次數
- 原子:
- 普通字元:'yue'
- 非列印字元:'\n'換行符等
- 通用字元:
- \w:匹配字母、數字、下劃線;等價於'[A-Za-z0-9_]'
- \W:匹配非字母、數字、下劃線;等價於 '[^A-Za-z0-9_]'
- \s:匹配任何空白字元,包括空格、製表符、換頁符
- \S:匹配任何非空白字元
- \d:匹配一個數字字元
- \D:匹配一個非數字字元
- \A:匹配字串開始
- \Z:匹配字串結束,如果存在換行,只匹配到換行前的結束字元
- \z:匹配字串結束
- \G:匹配最後匹配完成的位置
- \n:匹配換行符
- \t:匹配製表符
- 元字元:
- ^:匹配字串開頭
- $:匹配字串結尾
- .:匹配除換行符(\n、\r)之外的任何單個字元,當re.DOTALL標記被指定時,可以匹配任意字元;\.匹配點自身
- []:原子集
- [^]:非原子集,不存在原子集中的字元
- *:匹配0或多個的前一個原子,元字元或原子集;貪婪模式,提取後面符合規則的所有字元
- +:匹配1或多個的前一個原子,元字元或原子集;貪婪模式
- ?:匹配0或1個的前一個原子,元字元或原子集,.*?這裡的?指的是.*;非貪婪模式
- |:模式選擇符,設定多個模式,匹配時,可以從中任意一個模式匹配,類似原子集
- ():模式單元符,將原子組合成一個大原子使用,用findall則只擷取pattern的()內的字串
- {n}:精確匹配n個前面表示式
- {n,m}:匹配n到m次由前面正則表示式定義的片段,貪婪模式
- 原子表(字符集):[p\wh],定義一組地位平等的原子,然後匹配的時候會取該原子集中任意一個原子進行匹配
- 例項:
- 匹配.com和.cn字尾的網址:[a-zA-Z]+://[^\s]*[.com|.cn]
- 匹配電話號碼:\d{4}-\d{7}|\d{3}-\d{8}
- 匹配電子郵箱:
- <br><a href='(.*?)'>
- [a-zA-Z+-][email protected][a-zA-Z-]+\.\w+([.-]\w+)*,郵箱通用
- 操作