python 3.x 爬蟲基礎---Requersts,BeautifulSoup4(bs4)


python 3.x 爬蟲基礎

python 3.x 爬蟲基礎---http headers詳解

python 3.x 爬蟲基礎---Urllib詳解

python 3.x 爬蟲基礎---Requersts,BeautifulSoup4(bs4)

python 3.x 爬蟲基礎---正則表達式

 

前言

其實前兩章都是python內置的爬蟲函數,大家都知道python有強大的第三方庫,今天我們就來說一下requests,BeautifulSoup4,selenium,lxml ,順便正則re也會在這篇文章中提及。

Requersts

參考文檔http://docs.python-requests.org/zh_CN/latest/user/quickstart.html

python實現的簡單易用的HTTP庫(第三方庫記得去導入)你不需要手動為 URL 添加查詢字串,也不需要對 POST 數據進行表單編碼。Keep-alive 和 HTTP 連接池的功能是 100% 自動化的,一切動力都來自於根植在 Requests 內部的 urllib3,使用起來比urllib簡潔很多。上面的得文檔有詳細的介紹,所以如果想系統的學習就直接觀看文檔即可。

操作屬性

import requests
response = requests.get('http://www.baidu.com')
print('文本形式的網頁源碼')
print(response.text)
print('二進制流形式打印')
print(response.content)
print('返回JSON格式,可能拋出異常')
print(response.json)
print('狀態碼')
print(response.status_code)
print('請求url')
print(response.url)
print('頭信息')
print(response.headers)
print('cookie信息')
print(response.cookies)

看一下運行結果:

傳遞參數

import requests
payload = {'key1': 'value1', 'key2': 'value2', 'key3': None}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.url)

運行結果:

傳遞headers

這個在python 3.x 爬蟲基礎---http headers詳解 有詳細的介紹不管是urllib還是request headers都是至關重要的,在這不過多敘述有興趣的自己去看一下吧。

請求方式

requests.get('http://httpbin.org/get')
requests.post('http://httpbin.org/post')
requests.put('http://httpbin.org/put')
requests.delete('http://httpbin.org/delete')
requests.head('http://httpbin.org/get')
requests.options('http://httpbin.org/get')

post訪問

通常,你想要發送一些編碼為表單形式的數據—非常像一個HTML表單。 要實現這個,只需簡單地傳遞一個字典給 data 參數。你的數據字典 在發出請求時會自動編碼為表單形式:

import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
print(r.text)

運行結果:

傳遞文件:

import requests
url = 'http://httpbin.org/post'
files = {'file': open('wyl.xls', 'rb')}
r = requests.post(url, files=files)

這個方式對你傳遞的復雜參數有很好的控制。

傳遞字符串:

import requests
import json
url = 'https://xxxxxxxx'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
#或者
r = requests.post(url, json=payload)

提示:選擇適當的http訪問。

超時設置

requests.get('http://xxxxx.com', timeout=1)

注:timeout 僅對連接過程有效,與響應體的下載無關。 timeout 並不是整個下載響應的時間限制,而是如果服務器在 timeout 秒內沒有應答,將會引發一個異常。

代理

import requests
proxies = {
  'http': 'http://10.10.1.10:3128',
  'https': 'http://10.10.1.10:1080',
}
requests.get('http://xxxx.com', proxies=proxies)

防爬蟲會涉及到ip限制,所以ip代理在爬蟲中會常用到,還有vpn代理等等吧。

重定向與請求歷史

默認情況下,除了 HEAD, Requests 會自動處理所有重定向。可以使用響應對象的 history 方法來追蹤重定向,head可以通過 allow_redirects 參數禁用重定向處理。

import requests
s=requests.get('http://github.com')
print(s.url)
print(s.status_code)
r=requests.get('http://github.com', allow_redirects=False)
print(r.url)
print(r.history)
r=requests.head('http://github.com');
print(r.url)
print(r.status_code)
r=requests.head('http://github.com', allow_redirects=True)
print(r.url)
print(r.history)

運行結果:

異常處理

所有Requests顯式拋出的異常都繼承自 requests.exceptions.RequestException

import requests
from requests.exceptions import ReadTimeout,HTTPError,RequestException
try:
    response = requests.get('http://www.baidu.com',timeout=0.5)
    print(response.status_code)
except ReadTimeout:
    print('timeout')
except HTTPError:
    print('httperror')
except RequestException:
    print('reqerror')

HTTPError:如果 HTTP 請求返回了不成功的狀態碼

Timeout:請求超時

ConnectionError:遇到網絡問題(如:DNS 查詢失敗、拒絕連接等)

TooManyRedirects:若請求超過了設定的最大重定向次數

RequestException:所有的requerst 異常

requests登陸的幾種方法

通過賬號與密碼

loginurl='https://xxxxx.com/check'  
formData={'username':'*****',  
          'password':'*****'}  
headers={'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/52.0'}  
res=req.post(loginurl,data=formData,headers=headers)  

通過cookies

    raw_cookies="k1=v1; k2=v2; k3=v3; 
    cookies={}  
    for line in raw_cookies.split(';'):  
        key,value=line.split('=',1)  
        cookies[key]=value  
    loginurl='http://xxxxxx.com'  
    res=req.post(loginurl,cookies=cookies)  
    print res.content  
    "訪問其它的頁面"  
    logi1="http://xxxxx.htm"  
    print req.post(logi1,cookies=cookies).content  

其中的cookies獲取后將cookies的值以字典的方式存儲,然后進行使用

通過session

import requests as req  
s=req.Session()  
param={'username':'****',  
       'password':'***'}  
url='https://xxxxxx'  
r=s.post(url,data=param,verify=False)  #登錄獲取登錄后的session  
print r.content  
print s.get('http://xxxxxxx',verify=False).content  #通過session訪問其它url

如果有ssl認證,可以在post的時候,加入認證的參數,取消ssl的認證校驗 requests.post(url,data=dataform,verify=False)

BeautifulSoup4(bs4)

參考文檔:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html

是一個可以從HTML或XML文件中提取數據的Python庫.它能夠通過你喜歡的轉換器實現慣用的文檔導航,查找,修改文檔的方式.urllib或者request請求完之后,就要對其操作,那么下面就來操作吧。其實可以把它理解為js/css中的選擇器來使用。

解析器

Beautiful Soup支持Python標准庫中的HTML解析器,還支持一些第三方的解析器,其中一個是LXML ,后面會有介紹。

對象的種類

Beautiful Soup將復雜HTML文檔轉換成一個復雜的樹形結構,每個節點都是Python對象,所有對象可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment

#1.tag

此對象與html和xml 中的tag相同

soup = BeautifulSoup('<div class="className">wangyanling</div>')
tag = soup.div
print('tag 對象輸出:')
print(tag)
print('查看類型')
print(type(tag))
print('#獲取tag的名字')
print(tag.name)
print('#Attributes')
print('#Attributes:獲取tag的屬性值 注tag是有多個屬性')
print(tag['class'])
print('添加屬性')
tag['id']='wylId'
print(tag)
print('#刪除屬性')
del tag['class']
print(tag)
print('#多值屬性')
css_soup = BeautifulSoup('<p class="body strikeout"></p>')
print(css_soup.p['class'])
print('#不明確的多值屬性')
id_soup = BeautifulSoup('<p id="my id"></p>')
print(id_soup.p['id'])
print('# 重新賦值')
print('#重復的值會進行合並')
rel_soup = BeautifulSoup('<p>Back to the <a rel="index">homepage</a></p>')
print(rel_soup.a['rel'])
rel_soup.a['rel'] = ['index', 'contents']
print(rel_soup.p)
print('xml 多值屬性')
'''xml_soup = BeautifulSoup('<p class="body strikeout"></p>', 'xml')
print(xml_soup.p['class'])'''

輸出結果:

 

#2.NavigableString

操作標簽嚇得字符串,我們就要用到NavigableString

soup = BeautifulSoup('<b class="index">wyl good</b>')
print('soup.string的類型(NavigableString)')
print(soup.string)
print(type(soup.string))
print('替換字符串')
soup.string.replace_with("王延領")
print(soup)

輸出結果:

注:一個字符串不能包含其它內容(tag能夠包含字符串或是其它tag),字符串不支持 .contents.string 屬性或 find() 方法.

#3.BeautifulSoup

表示的是一個文檔的全部內容,大部分時候,可以把它當作 Tag 對象。它支持 遍歷文檔樹搜索文檔樹 中描述的大部分的方法.他是沒有name合attribute的。

#4.Comment

以上三個對象幾乎包換了你所有html與xml的內容,但是你是不是覺得還有一個東西沒有涉及到,那就是html xml不編輯的注解。

markup = "<b><!--我是一個注釋不要意思--></b>"
soup = BeautifulSoup(markup)
comment = soup.b.string
print('html中的注釋')
print(comment)
print(type(comment))

輸出結果:

看輸出Comment是不是一個特殊的NavigableString管他呢。

遍歷文檔樹

上面有提到遍歷文檔樹與搜索文檔樹,那么就來一起學習一下。其實從名字就能知道踏實去循環遍歷獲取html xml內容的。

我們可以把它分為子節點,父節點,兄弟節點,回退與前進是不是css/js選擇器的感覺其實差不多。

為了方便我寫了一些html

html_doc = """
<html>
    <head>
        <title>The Dormouse's story</title>
        <stype>
        .body{
        color:red;
        }
        </stype>
    </head>
<p class="title"><b>這是一個不太好的html</b></p>
<p class="story">這是一個段落
<a href="http:http://www.cnblogs.com/kmonkeywyl/p/8482962.html%20" id="link1">python 3.x 爬蟲基礎---常用第三方庫</a>,
<a href="http://www.cnblogs.com/kmonkeywyl/p/8458442.html" class="sister" id="link2">python 3.x 爬蟲基礎---Urllib詳解</a>
<a href="http://www.cnblogs.com/kmonkeywyl/p/8435533.html" class="sister" id="link3">python 3.x 爬蟲基礎---http headers詳解</a>;
</p>
<p class="story">...</p>
"""
View Code

#1.子節點

soup = BeautifulSoup(html_doc)
print('1.利用tag的name獲取信息')
print(soup.head)
print('2.獲取第一個p標簽')
print(soup.p)
print('3.獲取第一p下的a')
print(soup.p.b)
print('4.tag的 .contents 屬性可以將tag的子節點以列表的方式輸出')
head_tag = soup.head
print(head_tag)
print(head_tag.contents)
print('5.通過tag的 .children 生成器,可以對tag的子節點進行循環')
i=0
for child in head_tag.children:
    print(i)
    i=i+1
    print(child)
print('6.descendants 操作soup的子孫節點(包括字符串)')
for child in head_tag.descendants:
    print(i)
    i=i+1
    print(child)
print('7.如果tag只有一個 NavigableString 類型子節點,那么這個tag可以使用 .string 得到子節點')
s_titl=soup.title
print(s_titl.string)
print('8.如果有多個字符串可以用strings循環獲得')
for string in soup.strings:
    print(repr(string))
print('9.stripped_strings去除空格')
for string in soup.stripped_strings:
    print(repr(string))

 #2.父節點

print('通過 .parent 屬性來獲取某個元素的父節點')
soup = BeautifulSoup(html_doc)
title_tag = soup.title
print(title_tag)
print('title 父節點')
print(title_tag.parent)
print('html 的父節點')
html_tag = soup.html
print(type(html_tag.parent))
print('BeautifulSoup的父節點 ')
print(soup.prent)
print('通過元素的 .parents 屬性可以遞歸得到元素的所有父輩節點')
link = soup.a
for parent in link.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)

輸出結果:

 

 

#3.兄弟節點

sibling_soup = BeautifulSoup("<a><b>text1</b><c>text2</c></a>")
print('next_sibling|previous_sibling 尋找兄弟節點')
print(sibling_soup.prettify())
print(sibling_soup.b.next_sibling)
print(sibling_soup.c.previous_sibling)
print('通過 .next_siblings 和 .previous_siblings 屬性可以對當前節點的兄弟節點迭代輸出')
soup = BeautifulSoup(html_doc)
for sibling in soup.a.next_siblings:
    print(repr(sibling))

輸出結果:

#4.回退與前進

HTML解析器把這段字符串轉換成一連串的事件: “打開<html>標簽”,”打開一個<head>標簽”,”打開一個<title>標簽”,”添加一段字符串”,”關閉<title>標簽”,”打開<p>標簽”,等等.Beautiful Soup提供了重現解析器初始化過程的方法.

通過 .next_elements.previous_elements 的迭代器就可以向前或向后訪問文檔的解析內容,就好像文檔正在被解析一樣:

soup = BeautifulSoup(html_doc)
for element in soup.a.next_elements:
    print(repr(element))

搜索文檔樹

 未完待續


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM