Python爬蟲基礎知識講解
Python
爬蟲主要是為了方便學習新語言和學習資料的爬取
1 瞭解robots.txt
1.1 基礎理解
robots.txt
是一個純文字檔案,在這個檔案中網站管理者可以宣告該網站中不想被robots訪問的部分,或者指定搜尋引擎只收錄指定的內容,一般域名後加/robots.txt
當一個搜尋機器人(有的叫搜尋蜘蛛)訪問一個站點時,它會首先檢查該站點根目錄下是否存在
robots.txt
,如果存在,搜尋機器人就會按照該檔案中的內容來確定訪問的範圍;如果該檔案不存在,那麼搜尋機器人就沿著連結抓取另外,
robots.txt
必須放置在一個站點的根目錄下,而且檔名必須全部小寫。robots.txt
寫作語法首先,我們來看一個
robots.txt
範例:https://fanyi.youdao.com/robots.txt
訪問以上具體地址,我們可以看到
robots.txt
的具體內容如下
User-agent: Mediapartners-Google Disallow: User-agent: * Allow: /fufei Allow: /rengong Allow: /web2/index.html Allow: /about.html Allow: /fanyiapi Allow: /openapi Disallow: /app Disallow: /?
以上文字表達的意思是允許所有的搜尋機器人訪問fanyi.youdao.com
站點下的所有檔案
具體語法分析:User-agent
:後面為搜尋機器人的名稱,後面如果是*
,則泛指所有的搜尋機器人;Disallow
:後面為不允許訪問的檔案目錄
1.2 使用robots.txt
robots.txt
自身是一個文字檔案。它必須位於域名的根目錄中並被命名為robots.txt
。位於子目錄中的 robots.txt
檔案無效,因為漫遊器只在域名的根目錄中查詢此檔案。例如,http://www.example.com/robots.txt
是有效位置,http://www.example.com/mysite/robots.txt
2 Cookie
由於http/https
協議特性是無狀態特性,因此需要伺服器在客戶端寫入cookie
,可以讓伺服器知道此請求是在什麼樣的狀態下發生
2.1 兩種cookie處理方式
cookie
簡言之就是讓伺服器記錄客戶端的相關狀態資訊,有兩種方式:
- 手動處理
通過抓包工具獲取cookie
值,然後將該值封裝到headers中
headers={
'cookie':"...."
}
在發起請求時把cookie封裝進去
- 自動處理
自動處理時,要明白cookie
的值來自伺服器端,在模擬登陸post
後,伺服器端建立並返回給客戶端
主要是通過session
會話物件來操作cookie
,session
作用:可以進行請求的傳送;如果請求過程中產生了cookie
會自動被儲存或攜帶在該session
物件中
建立session
物件:session=requests.Session()
,使用session
物件進行模擬登陸post
請求傳送(cookie
會被儲存在session
中)
傳送session
請求:session.post()
在傳送時session
物件對要請求的頁面對應get
請求進行傳送(攜帶了cookie
)
3 常用爬蟲方法
用python
爬取資料解析原理:
- 標籤定位
- 提取標籤、標籤屬性中儲存的資料值
3.1 bs4
3.1.1 基礎介紹
bs4
進行網頁資料解析
bs4
解析原理:
- 通過例項化一個
BeautifulSoup
物件,並且將頁面原始碼資料載入到該物件中 - 通過呼叫
BeautifulSoup
物件中相關的屬性或者方法進行標籤定位和資料提取
環境安裝:
pip install bs4
pip install lxml
3.1.2 bs4使用
3.1.2.1 獲取解析物件
如何例項化BeautifulSoup
物件:
導包from bs4 import BeautifulSoup
物件的例項化,有兩種,本地和遠端:
- 將本地的
html
文件中的資料載入到該物件中
fp = open('./test.html','r',encoding='utf-8')
soup=BeautifulSoup(fp,'lxml') #指定lxml解析方式
- 將網際網路上獲取的頁面原始碼載入到該物件中
page_text = response.text
soup=BeautifulSoup(page_text,'lxml')
3.1.2.2 使用bs4解析
使用bs4
提供的用於資料解析的方法和屬性:
-
soup.tagName
:返回的是文件中第一次出現的tagName
對應的標籤,比如soup.a
獲取第一次出現的a
標籤資訊 -
soup.find()
:
在使用find('tagName')
效果是等同於soup.tagName
;
進行屬性定位,soup.find(‘div’,class_(或id或attr)='song')
:示例就是定位帶有class='song'
的div
標籤,class_
必須有下劃線是為了規避python
關鍵字
還可以是其他比如:soup.find(‘div’,id='song')
:定位id是song的div標籤
soup.find(‘div’,attr='song')
:定位attr是song的div標籤 -
soup.find_all('tagName')
:返回符合要求的所有標籤(列表)
select
用法:
select('某種選擇器(id,class,標籤..選擇器)')
返回的是一個列表- 層級選擇器:參考jquyer層級選擇器
獲取標籤之間文字資料
可以使用text
或string
或get_text()
,主要區別:
text
或get_text()
可以獲取某一個標籤中所有的文字內容string
:只可以獲取該標籤下面直系的文字內容
獲取標籤中屬性值:
- 使用
python
獲取字典方法獲取,比如:soup.a['href']
就是獲取<a>
中的href
值
3.1.2 使用例子
import os
import requests
from bs4 import BeautifulSoup
headers={
'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
url="https://www.test.com/chaxun/zuozhe/77.html"
def getPoems():
res= requests.get(url=url,headers=headers)
res.encoding='UTF-8'
page_text=res.text
#在首頁解析出章節
soup = BeautifulSoup(page_text,'lxml')
shici_list = soup.select(".shici_list_main > h3 > a")
shici_name=[]
for li in shici_list:
data_url = "https://www.test.com"+li['href']
# print(li.string+"======="+data_url)
shici_name.append(li.string)
detail_res = requests.get(url=data_url,headers=headers)
detail_res.encoding='UTF-8'
detail_page_text=detail_res.text
detail_soup = BeautifulSoup(detail_page_text,'lxml')
detail_content = detail_soup.find("div",class_="item_content").text
# print(detail_content)
with open("./shici.txt",'a+',encoding= 'utf8') as file:
if shici_name.count(li.string)==1:
file.write(li.string)
file.write(detail_content+"\n")
print(li.string+"下載完成!!!!")
if __name__=="__main__":
getPoems()
3.2 xpath
xpath
解析:最常用且最便捷高效的一種解析方式
3.2.1 xpath基礎介紹
xpath
解析原理:
- 例項化一個
etree
的物件,且需要將被解析的頁面原始碼資料載入到該物件中 - 呼叫
etree
物件中的xpath
方法結合著xpath
表示式實現標籤的定位和內容的捕獲
環境安裝:
pip install lxml
3.2.2 xpath使用
3.2.2.1 獲取相關物件
先例項化一個etree
物件,先導包:from lxml import etree
- 將本地的
html
文件中的原始碼資料載入到etree
物件中
tree=etree.parse(filepath)
- 可以將從網際網路上獲取的原始碼資料載入到該物件中
page_text = response.text
tree=etree.HTML(page_text)
3.2.2.2 通過xpath解析
通過xpath
表示式:tree.xpath(xpath表示式)
:
xpath
表示式:
/
:表示的是從根節點開始定位,表示的是一個層級//
:表示的是多個層級,可以表示從任意位置開始定位- 屬性定位:
tag[@attrName='attrValue']
比如//div[@class='song']
表示的是獲取到任意位置class='song'
的<div>
標籤 - 索引定位:
//div[@class='song']/p[3]
表示的是任意位置class='song'
的<div>
標籤下面的第三個<p>
標籤,注意:
索引定位是從1
開始的 - 取文字:
/text()
:獲取的是標籤中直系文字內容
//text()
:標籤中非直系的文字內容(所有的文字內容) - 取屬性:
/@attrName
:獲取某個屬性的值,比如://img/@src
獲取任意的img
標籤的src
值
3.2.3 使用例子
import requests
from lxml import etree
import re
headers={
'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"
}
url="https://www.test.com/chaxun/zuozhe/77.html"
def getPoemsByXpath():
res= requests.get(url=url,headers=headers)
res.encoding='UTF-8'
page_text=res.text
#在首頁解析出章節
tree = etree.HTML(page_text)
shici_list = tree.xpath("//div[@class='shici_list_main']")
shici_name_out=''
for shici in shici_list:
#此處使用相對路徑
shici_name=shici.xpath("h3/a/text()")[0]
# print(shici_name)
shici_text_list=shici.xpath("div//text()")
# print(shici_text_list)
with open("./shicibyxpath.txt",'a+',encoding= 'utf8') as file:
if shici_name_out!=shici_name:
file.write(shici_name+"\n")
for text in shici_text_list:
if "展開全文"==text or "收起"==text or re.match(r'^\s*$',text)!=None or re.match(r'^\n\s*$',text)!=None:
continue
re_text=text.replace(' ','').replace('\n','')
file.write(re_text+"\n")
if shici_name_out!=shici_name:
print(shici_name+"下載完成!!!!")
shici_name_out=shici_name
if __name__=="__main__":
getPoemsByXpath()