Requests庫(kù)
以管理員身份運(yùn)行cmd磕谅,輸入pip install requests
业稼,等待安裝突倍。安裝成功后妖滔,可進(jìn)入IDLE使用requests庫(kù):
>>>import requests
>>>r=requests.get("http://www.baidu.com")
>>> r.status_code #檢測(cè)這個(gè)請(qǐng)求的狀態(tài)碼
200
>>>r.encoding = 'utf-8'
>>>r.text
'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下俭尖,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn"></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新聞</a> <a href=http://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地圖</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>視頻</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>貼吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登錄</a> </noscript> <script>document.write(\'<a + encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">登錄</a>\');</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多產(chǎn)品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>關(guān)于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必讀</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意見(jiàn)反饋</a> 京ICP證030173號(hào) <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n'
Requests庫(kù)的7個(gè)主要使用方法
方法 | 說(shuō)明 |
---|---|
requests.requests() | 構(gòu)造一個(gè)請(qǐng)求氢惋,支撐以下各方法的基礎(chǔ)方法 |
requests.get() | 獲取HTML網(wǎng)頁(yè)的主要方法,對(duì)應(yīng)于HTTP的GET |
requests.head() | 獲取HTTP網(wǎng)頁(yè)頭信息的主要方法稽犁,對(duì)應(yīng)于HTTP的HEAD |
requests.post() | 向HTML網(wǎng)頁(yè)提交POST請(qǐng)求的方法焰望,對(duì)應(yīng)于HTTP的POST |
requests.put() | 向HTML網(wǎng)頁(yè)提交PUT請(qǐng)求的方法,對(duì)應(yīng)于HTTP的PUT |
requests.patch() | 向HTML網(wǎng)頁(yè)提交局部請(qǐng)求已亥,對(duì)應(yīng)于HTTP的PATCH |
requests.delete() | 向HTML頁(yè)面提交刪除請(qǐng)求熊赖,對(duì)應(yīng)于HTTP的DELETE |
實(shí)際上requests庫(kù)只有一個(gè)方法,那就是requests()方法陷猫,其他6個(gè)方法都是通過(guò)requests()方法進(jìn)行封裝的
get()方法
requests.get(url,params=None,**kwargs)
`r = requests.get(url)
構(gòu)造一個(gè)向服務(wù)器請(qǐng)求資源的Requests對(duì)象
返回一個(gè)包含服務(wù)器資源的Response對(duì)象
url:擬獲取頁(yè)面的url鏈接
params:url中的額外參數(shù)秫舌,字典或字節(jié)流格式,可選
**kwargs:12個(gè)控制訪問(wèn)的參數(shù)
>>> import requests
>>> r = requests.get("http://www.baidu.com")
>>> print(r.status_code)
200
>>> type(r) #返回r的類(lèi)型:一個(gè)類(lèi)
<class 'requests.models.Response'>
>>> r.headers #返回get請(qǐng)求頁(yè)面的頭部信息
{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Mon, 05 Aug 2019 12:13:55 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:32 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
>>>
Response對(duì)象的屬性
屬性 | 說(shuō)明 |
---|---|
r.status_code | HTTP請(qǐng)求的返回狀態(tài)绣檬,200-成功足陨,404-失敗 |
r.text | HTTP響應(yīng)內(nèi)容的字符串形式,即url對(duì)應(yīng)的頁(yè)面內(nèi)容 |
r.encoding | 從HTTP header中猜測(cè)的響應(yīng)內(nèi)容編碼方式 |
r.apparent_encoding | 從內(nèi)容中分析出的響應(yīng)內(nèi)容編碼方式 |
r.content | HTTP響應(yīng)的二進(jìn)制形式 |
r.encoding:如果header中不存在charset娇未,則認(rèn)為編碼ISO-8859-1
r.text根據(jù)r.encoding顯示網(wǎng)頁(yè)內(nèi)容
r.apparent_encoding:根據(jù)網(wǎng)頁(yè)內(nèi)容分析出編碼方式墨缘,可以看作是r.encoding的備選
爬去網(wǎng)頁(yè)的通用代碼框架
異常 | 說(shuō)明 |
---|---|
requests.ConnectionError | 網(wǎng)絡(luò)連接錯(cuò)誤異常 |
requests.HTTPError | HTTP錯(cuò)誤異常 |
requests.URLrequired | URL缺失異常 |
requests.TooManyRedirects | 超過(guò)最大重定向次數(shù),產(chǎn)生重定向異常 |
requests.ConnectTimeout | 連接遠(yuǎn)程服務(wù)器超時(shí)異常 |
requests.Timeout | 請(qǐng)求URL超時(shí) |
r.raise_for_statis() | 如果不是200零抬,產(chǎn)生異常requests.HTTPError |
通用代碼框架:
import requests
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "產(chǎn)生異常"
if __name__ == "__main__":
url = "http://www.baidu.com"
print(getHTMLText(url))
HTTP協(xié)議
HTTP镊讼,Hypertext Transfer Protocol,超文本傳輸協(xié)議
HTTP是一個(gè)基于“請(qǐng)求與響應(yīng)”模式的平夜、無(wú)狀態(tài)的應(yīng)用層協(xié)議
HTTP協(xié)議采用URL作為定位網(wǎng)絡(luò)資源的標(biāo)識(shí)蝶棋,URL格式:
http://host[:port][path]
host:合法的Internet主機(jī)域名或IP地址
port:端口號(hào),缺省端口為80
path:請(qǐng)求資源路徑
HTTP協(xié)議對(duì)資源的操作
方法 | 說(shuō)明 |
---|---|
get | 請(qǐng)求獲取url位置的資源 |
head | 請(qǐng)求獲取url位置資源的響應(yīng)信息報(bào)告忽妒,即獲得該資源的頭部信息 |
post | 請(qǐng)求向url位置的資源后附加新的數(shù)據(jù) |
put | 請(qǐng)求向url位置存儲(chǔ)一個(gè)資源玩裙,覆蓋原url位置的資源 |
patch | 請(qǐng)求局部更新url位置的資源兼贸,即改變部分內(nèi)容 |
delete | 請(qǐng)求刪除url位置的資源 |
requests.requetst(methon, url, **kwargs)
· method:請(qǐng)求方式
· url:擬獲取頁(yè)面的url鏈接
· **kwargs:控制訪問(wèn)參數(shù),共13個(gè)
· method:
r = requests.requetst('GET', url, **kwargs)
r = requests.requetst('HEAD', url, **kwargs)
......
· **kwargs:控制訪問(wèn)的參數(shù)吃溅,均為可選項(xiàng)
params:字典或字節(jié)序列溶诞,作為參數(shù)增加到url中
data:字典、字節(jié)序列或文件對(duì)象决侈,作為Request的內(nèi)容
json:json格式的數(shù)據(jù)螺垢,作為Request的內(nèi)容
headers:字典,HTTP定制頭
cookies:字典或CookieJar赖歌,Request中的cookie
auth:元組枉圃,支持HTTP認(rèn)證功能
files:字典類(lèi)型,傳輸文件
timeout:設(shè)定超時(shí)時(shí)間俏站,秒為單位
proxies:字典類(lèi)型讯蒲,設(shè)定訪問(wèn)代理服務(wù)器,可以增加登錄認(rèn)證
allow_redirects:
stream:
verify:
cert:本地SSL證書(shū)路徑
網(wǎng)絡(luò)爬蟲(chóng)
網(wǎng)絡(luò)爬蟲(chóng)的尺寸
小規(guī)模肄扎,數(shù)據(jù)量小墨林,爬取速度不敏感:Requests庫(kù)
中規(guī)模,數(shù)據(jù)規(guī)模較大犯祠,爬取速度敏感:Scrapy庫(kù)
大規(guī)模旭等,搜索引擎,爬取速度關(guān)鍵:定制開(kāi)發(fā)
網(wǎng)絡(luò)爬蟲(chóng)的限制
· 來(lái)源審查:判斷User-Agent進(jìn)行限制
檢查來(lái)訪HTTP協(xié)議頭的User-Agent域衡载,只響應(yīng)瀏覽器友好爬蟲(chóng)的訪問(wèn)
· 發(fā)布公告:Robots協(xié)議
Robots協(xié)議
Robos Exclusion Standard搔耕,網(wǎng)絡(luò)爬蟲(chóng)排除標(biāo)準(zhǔn)
作用:網(wǎng)站告知網(wǎng)絡(luò)爬蟲(chóng)哪些可以抓取,哪些不行
形式:在網(wǎng)站根目錄下的robots.text文件
案例:京東的Robots協(xié)議
User-agent: * #對(duì)于任意來(lái)源網(wǎng)絡(luò)爬蟲(chóng)痰娱,定義為User-agent
Disallow: /?* #任何爬蟲(chóng)不允許訪問(wèn)以弃榨?開(kāi)頭的路徑
Disallow: /pop/*.html #
Disallow: /pinpai/*.html?*
#一下四個(gè)網(wǎng)絡(luò)爬蟲(chóng)不允許爬取jd的任何資源
User-agent: EtaoSpider
Disallow: /
User-agent: HuihuiSpider
Disallow: /
User-agent: GwdangSpider
Disallow: /
User-agent: WochachaSpider
Disallow: /
注意:#注釋?zhuān)?代表所有,/代表根目錄
Requests庫(kù)網(wǎng)絡(luò)爬蟲(chóng)5個(gè)案例
1.jd商品頁(yè)面的爬取
import requests
url = "https://item.jd.com/2967929.html"
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[:1000])
except:
print("爬取失敗")
※:一個(gè)普通基本的爬取
2.亞馬遜商品頁(yè)面的爬取
import requests
url = "https://www.amazon.cn/gp/product/B01M8L5Z3Y"
try:
kv = {'user-agent':'Mozilla/5.0'}
r = requests.get(url,headers=kv)
r.raise_for_status()
r.encoding = r.apparent_encoding
print(r.text[1000:2000])
except:
print("爬取失敗")
※:如果不進(jìn)行headers的修改梨睁,這次爬取會(huì)以python-requests進(jìn)行請(qǐng)求鲸睛,而amazon會(huì)拒絕這種請(qǐng)求;改變headers字段坡贺,模擬成瀏覽器對(duì)amazon服務(wù)器發(fā)出請(qǐng)求官辈。
3.網(wǎng)絡(luò)搜索關(guān)鍵詞提交
import requests
keyword = "Python"
try:
kv = {'wd':keyword}
r = requests.get("http://www.baidu.com/s",params=kv)
print(r.request.url)
r.raise_for_status()
print(len(r.text))
except:
print("爬取失敗")
※:params:關(guān)鍵詞
4.網(wǎng)絡(luò)圖片的爬取和存儲(chǔ)
import requests
import os
url = "http://img0.dili360.com/ga/M02/33/7C/wKgBzFSbqQyAJVAuAARB8cSWH_w695.tub.jpg"
root = "D://pics//"
path = root + url.split('/')[-1] #根目錄,加上以/分割的url的最后一個(gè)
try:
if not os.path.exists(root): #如果路徑不存在遍坟,則創(chuàng)建路徑
os.mkdir(root)
if not os.path.exists(path): #如果已存在拳亿,則爬取圖片地址
r = requests.get(url)
with open(path, 'wb') as f:
f.write(r.content)
f.close()
print("文件保存成功")
else:
print("文件已存在")
except:
print("爬取失敗")
BeautifulSoup庫(kù)
Beautiful Soup的理解
<html> 標(biāo)簽樹(shù)
<body>
<p class="title"> ... </p>
</body>
</html>
Beautiful Soup庫(kù)是解析、遍歷愿伴、維護(hù)“標(biāo)簽書(shū)”的功能庫(kù)
基本元素 | 說(shuō)明 |
---|---|
Tag | 標(biāo)簽肺魁,用<>和</>標(biāo)明開(kāi)頭和結(jié)尾 |
Name | 標(biāo)簽的名字,<p>...</p>的名字是'p'隔节,格式:<tag>.name |
Attributes | 標(biāo)簽的屬性鹅经,字典形式組織胡桨,格式:<tag>.attrs |
NavigableString | 標(biāo)簽內(nèi)非屬性字符串,<>...</>中字符串瞬雹,格式:<tag>.string |
Comment | 標(biāo)簽內(nèi)字符串的注釋部分,一種特殊的Comment類(lèi)型 |
引用方式:
from bs4 import BeautifulSoup
import bs4
基于bs4庫(kù)的HTML內(nèi)容遍歷方法
標(biāo)簽樹(shù)的下行遍歷
屬性 | 說(shuō)明 |
---|---|
.contents | 子節(jié)點(diǎn)列表刽虹,將<tag>所有兒子節(jié)點(diǎn)存入列表 |
.children | 子節(jié)點(diǎn)的迭代類(lèi)型酗捌,與.contents類(lèi)似,用于循環(huán)遍歷兒子節(jié)點(diǎn) |
.descendants | 子孫節(jié)點(diǎn)的迭代類(lèi)型涌哲,包含所有子孫節(jié)點(diǎn)胖缤,用于循環(huán)遍歷 |
標(biāo)簽樹(shù)的上行遍歷
屬性 | 說(shuō)明 |
---|---|
.parent | 節(jié)點(diǎn)的父親標(biāo)簽 |
.parents | 節(jié)點(diǎn)先輩標(biāo)簽的迭代類(lèi)型,用于循環(huán)遍歷先輩類(lèi)型 |
標(biāo)簽樹(shù)的平行遍歷
屬性 | 說(shuō)明 |
---|---|
.next_sibling | 返回按照HTML文本順序的下一個(gè)平行節(jié)點(diǎn)標(biāo)簽 |
.previous_sibling | 返回按照HTML文本順序的上一個(gè)平行節(jié)點(diǎn)標(biāo)簽 |
.next_siblings | 迭代類(lèi)型阀圾,返回后續(xù)所有 |
.previous_siblings | 迭代類(lèi)型哪廓,返回之前所有 |
所有平行遍歷需要發(fā)生在同一個(gè)父節(jié)點(diǎn)下
基于bs4庫(kù)的HTML格式輸出
如何讓<html>內(nèi)容更加友好的顯示?
prettify()方法:為html文本的內(nèi)容和標(biāo)簽增加換行符
>>>print(soup.a.prettify())
<a class="py1" id="link1">
Basic Python
</a>
信息組織與提取方法
信息標(biāo)記的三種形式
XML:xXtensible Markup Language
<name> ... </name>
<name />
<! - - - - >
XML實(shí)例:
<person>
<firstname>An</firstname>
<lastname>Ran</lastname>
<address>
<streetAddr>沙河口區(qū)</streetAddr>
<city>大連市</city>
<zipcode>116021</zipcode>
</address>
<prof>Computer System</prof>Security</city>
</persom>
JSON:JavaScript Object Notation
"key" : "value"
"key" : ["value1" , "value2"]
"key" : {"subkey" : "subvalue"}
JSON實(shí)例:
{
"firstname" : "An" ,
"lastname" : "Ran" ,
"address" : {
"streetAddr" : "沙河口區(qū)" ,
"city" : "大連市" ,
"zipcode" : "116021" ,
} ,
"prof" : ["Computer System" , "Security"]
}
YAML:YAML Ain't Markup Language
key : value
key : #Comment
-value1
-value2
key :
subkey : subvalue
firstname : An
lastname : Ran
address :
streetAddr : 沙河口區(qū)
city : 大連市
zipcode : 116021
prof :
-Computer System
-Security
比較
類(lèi)型 | 說(shuō)明 |
---|---|
XML | 擴(kuò)展性好初烘,但繁瑣涡真。Internet上的信息交互與傳遞。 |
JSON | 信息有類(lèi)型肾筐,適合程序處理(js)哆料,較XML簡(jiǎn)潔。移動(dòng)應(yīng)用云端和節(jié)點(diǎn)的信息通信吗铐,無(wú)注釋东亦。 |
YAML | 信息無(wú)類(lèi)型,文本信息比例高唬渗,可讀性好典阵。各類(lèi)系統(tǒng)的配置文件,有注釋易讀镊逝。 |
信息提取的一般方法
方法一:完整解析信息的標(biāo)記形式壮啊,再提取關(guān)鍵信息。
XML JSON YAML
需要解析標(biāo)記器 例如:bs4庫(kù)的標(biāo)簽遍歷樹(shù)
優(yōu)點(diǎn):信息解析準(zhǔn)確
缺點(diǎn):提取過(guò)程繁瑣蹋半,速度慢
方法二:無(wú)視標(biāo)記形式他巨,直接搜索關(guān)鍵信息。
搜索
對(duì)信息的文本查找函數(shù)即可减江。
優(yōu)點(diǎn):提取過(guò)程簡(jiǎn)潔染突,速度較快。
缺點(diǎn):提取結(jié)果準(zhǔn)確性與信息內(nèi)容相關(guān)辈灼。
融合方法:結(jié)合形式解析與搜索方法份企,提取關(guān)鍵信息。
XML JSON YAML 搜索
需要標(biāo)記解析器及文本查找函數(shù)巡莹。
實(shí)例:提取HTML中所有URL鏈接
思路:1)搜索到所有<a>標(biāo)簽
2)解析<a>標(biāo)簽格式司志,提取href后的鏈接內(nèi)容
>>> soup = BeautifulSoup(demo,"html.parser")
>>> for link in soup.find_all('a'):
print(link.get('href'))
http://www.icourse163.org/course/BIT-268001
http://www.icourse163.org/course/BIT-1001870001
基于bs4庫(kù)的HTML內(nèi)容查找方法
返回一個(gè)列表類(lèi)型甜紫, 存儲(chǔ)查找的結(jié)果
<>.find_all(name,attrs,recursive,string,**kwargs)
· name:對(duì)標(biāo)簽名稱(chēng)的檢索字符串
>>> soup.find_all('a')
[<a class="py1" id="link1">Basic Python</a>, <a class="py2" id="link2">Advanced Python</a>]
>>> soup.find_all(['a','b'])
[<b>The demo python introduces several python courses.</b>, <a class="py1" id="link1">Basic Python</a>, <a class="py2" id="link2">Advanced Python</a>]
>>>
>>> for tag in soup.find_all(True):
print(tag.name)
html
head
title
body
p
b
p
a
a
>>> for tag in soup.find_all(re.compile('b')):
print(tag.name)
body
b
attrs:對(duì)標(biāo)簽屬性值的檢索字符串,可標(biāo)注屬性檢索
>>> soup.find_all('p','course') #查找p標(biāo)簽中骂远,含有course屬性值的標(biāo)簽
[<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" id="link1">Basic Python</a> and <a class="py2" id="link2">Advanced Python</a>.</p>]
>>> soup.find_all(id='link1') #查找id等于'link1'的標(biāo)簽
[<a class="py1" id="link1">Basic Python</a>]
recursive:是否對(duì)子孫全部檢索囚霸,默認(rèn)True
True:搜索根節(jié)點(diǎn)的兒子節(jié)點(diǎn)之后的節(jié)點(diǎn)
False:只搜索到根節(jié)點(diǎn)的兒子節(jié)點(diǎn),停止
>>> soup.find_all('a',recursive=False)
[]
#說(shuō)明從soup的根節(jié)點(diǎn)開(kāi)始激才,即根節(jié)點(diǎn)的兒子節(jié)點(diǎn)無(wú)a標(biāo)簽拓型,a標(biāo)簽在根節(jié)點(diǎn)的孫子節(jié)點(diǎn)之后
string:<>...</>中字符串區(qū)域的檢索字符串
>>> soup.find_all(string = re.compile("python"))
['This is a python demo page', 'The demo python introduces several python courses.']
<tag>(..) 等價(jià)于 <tag>.find_all(..)
soup(..) 等價(jià)于 soup.find_all(..)
擴(kuò)展方法
方法 | 說(shuō)明 |
---|---|
<>.find() | 搜索且只返回一個(gè)結(jié)果,同.find_all()參數(shù) |
<>.find_parents() | 在先輩節(jié)點(diǎn)中搜索瘸恼,返回列表類(lèi)型劣挫,同.find_all()參數(shù) |
<>.find_parent() | 在先輩節(jié)點(diǎn)中返回一個(gè)結(jié)果,同.find()參數(shù) |
<>.find_next_siblings() | 在后續(xù)平行節(jié)點(diǎn)中搜索东帅,返回列表類(lèi)型压固,同.find_all()參數(shù) |
<>.find_next_sibling() | 在后續(xù)平行節(jié)點(diǎn)中返回一個(gè)結(jié)果,同.find()參數(shù) |
<>.find_previous)siblings() | 在前序平行節(jié)點(diǎn)中搜索靠闭,返回列表類(lèi)型帐我,同.find_all()參數(shù) |
<>.find_previous_sibling() | 在前序平行節(jié)點(diǎn)中返回一個(gè)結(jié)果,同.find()參數(shù) |
Re庫(kù):正則表達(dá)式
regular expression
正則表達(dá)式常用操作符
操作符 | 說(shuō)明 | 實(shí)例 |
---|---|---|
. | 表示任何單個(gè)字符 | |
[ ] | 字符集愧膀,對(duì)單個(gè)字符給出取值范圍 | [abc]表示a焚刚、b、c扇调,[a-z]表示a到z單個(gè)字符 |
[^ ] | 非字符集矿咕,對(duì)單個(gè)字符給出排除范圍 | [^abc]表示非a或b或的單個(gè)字符 |
* | 前一個(gè)字符0次或無(wú)限次擴(kuò)展 | abc*表示ab、abc狼钮、abcc碳柱、abccc等 |
+ | 前一個(gè)字符1次或無(wú)限次擴(kuò)展 | abc+表示abc、abcc熬芜、abccc等 |
? | 前一個(gè)字符0次或1次擴(kuò)展 | abc?表示ab莲镣、abc |
丨 | 左右表達(dá)式任意一個(gè) | abc丨def表示abc、def |
{m} | 擴(kuò)展前一個(gè)字符m次 | ab{2}c表示abbc |
{m,n} | 擴(kuò)展前一個(gè)字符m至n次(含n) | ab{1,2}c表示abc涎拉、abbc |
^ | 匹配字符串開(kāi)頭 | ^abc表示abc在一個(gè)字符串的開(kāi)頭 |
$ | 匹配字符串結(jié)尾 | abc$表示abc且在一個(gè)字符串的結(jié)尾 |
( ) | 分組標(biāo)記瑞侮,內(nèi)部只能使用丨操作符 | (abc)表示abc,(abc丨def)表示abc鼓拧、def |
\d | 數(shù)字半火,等價(jià)于[0-9] | |
\w | 單詞字符,等價(jià)于[A-Za-z0-9_] |
元字符 | 描述 |
---|---|
. | 句號(hào)匹配任意單個(gè)字符季俩,除了換行符 |
[ ] | 字符種類(lèi)钮糖,匹配括號(hào)內(nèi)的任意字符 |
[^ ] | 否對(duì)的字符種類(lèi),匹配除了方括號(hào)內(nèi)的任意字符 |
* | 匹配>=0個(gè)重復(fù)在*號(hào)之前的字符 |
+ | 匹配>=1個(gè)重復(fù)的+號(hào)之前的字符 |
? | 標(biāo)記?之前的字符為可選 |
{n,m} | 匹配num個(gè)大括號(hào)之前的字符(n<=num<=m) |
(xyz) | 字符集酌住,匹配與xyz完全相等的字符串 |
丨 | 或運(yùn)算符店归,匹配符號(hào)前或后的字符 |
\ | 專(zhuān)一字符用于匹配保留字符(表內(nèi)) |
\d | 數(shù)字阎抒,等價(jià)于[0-9] |
\w | 單詞字符,等價(jià)于[A-Za-z0-9_ ] |
^ | 從開(kāi)始行開(kāi)始匹配 |
$ | 從末端開(kāi)始匹配 |
Re庫(kù)的基本使用
Re庫(kù)是python的標(biāo)準(zhǔn)庫(kù)消痛,主要用于字符串匹配
調(diào)用:import re
raw string類(lèi)型(原生字符串類(lèi)型)
表示:r'text'
例:r'[1-9]\d{5}'
Re庫(kù)主要功能函數(shù)
函數(shù) | 說(shuō)明 |
---|---|
re.search() | 在一個(gè)字符串中搜索匹配正則表達(dá)式的第一個(gè)位置且叁,返回match對(duì)象 |
re.match() | 從一個(gè)字符串的開(kāi)始位置起匹配正則表達(dá)式,返回match對(duì)象 |
re.findall() | 搜索字符串秩伞,以列表類(lèi)型返回全部能匹配的子串 |
re.spilt() | 將一個(gè)字符串按照正則表達(dá)式匹配結(jié)果進(jìn)行分割谴古,返回列表類(lèi)型 |
re.finditer() | 搜索字符串,返回一個(gè)匹配結(jié)果的迭代類(lèi)型稠歉,每個(gè)迭代元素是match對(duì)象 |
re.sub() | 在一個(gè)字符串中替換所有匹配正則表達(dá)式的子串,返回替換后的字符串 |
1汇陆、re.search(pattern, string, flags=0)
在一個(gè)字符串中搜索匹配正則表達(dá)式的第一個(gè)位置怒炸,返回match對(duì)象
· pattern:正則表達(dá)式的字符串或原生字符串表示
· string:待匹配字符串
· flags:正則表達(dá)式使用時(shí)的控制標(biāo)記
常用標(biāo)記 | 說(shuō)明 |
---|---|
re.I re.IGNORECASE | 忽略正則表達(dá)式的大小寫(xiě),[A-Z]能夠匹配小寫(xiě)字符 |
re.M re.MULTILINE | 正則表達(dá)式中的^操作符能夠?qū)⒔o定字符串的每行當(dāng)作匹配開(kāi)始 |
re.S re.DOTALL | 正則表達(dá)式中的.操作符能夠匹配所有字符串毡代,默認(rèn)匹配換行外的所有字符 |
>>> import re
>>> match = re.search(r'[1-9]\d{5}', 'BIT 100081')
>>> if match:
print(match.group(0))
#.search()是在整體中搜索的
100081
2阅羹、re.match(pattern, string, flags=0)
>>> import re
>>> match = re.match(r'[1-9]\d{5}', 'BIT 100081')
>>> if match:
match.group(0)
#match從字符串位置搜索,字母不能匹配數(shù)字教寂,為空
>>> match = re.match(r'[1-9]\d{5}', '100081 BIT')
>>> if match:
print(match.group(0))
#調(diào)換一下目標(biāo)字符串中字母與數(shù)字的位置捏鱼,就可了
100081
3、re.findall(pattern, string, flags=0)
搜索字符串酪耕,以列表類(lèi)型返回全部能匹配的子串
>>> import re
>>> ls = re.findall(r'[1-9]\d{5}', 'BIT100081 TSU100084')
>>> ls
['100081', '100084']
4导梆、re.spilt(pattern, string, maxspilt=0, flags=0)
maxspilt:最大分割數(shù)
將一個(gè)字符串按照正則表達(dá)式匹配結(jié)果進(jìn)行分割,返回列表類(lèi)型
>>> import re
>>> re.split(r'[1-9]\d{5}', 'BIT100081 TSU100084')
['BIT', ' TSU', '']
將一個(gè)正則表達(dá)式匹配字符串迂烁,匹配的部分去掉看尼,去掉之后的部分作為元素放在列表里。
5盟步、re.finditer(pattern, string, flags=0)
搜索字符串藏斩,返回一個(gè)匹配結(jié)果的迭代類(lèi)型,每個(gè)迭代元素是match對(duì)象却盘。
>>> import re
>>> for m in re.finditer(r'[1-9]\d{5}', 'BIT100081 TSU100084'):
if m:
print(m.group(0))
100081
100084
6狰域、re.sub(pattern, repl, string, count=0, flags=0)
· repl:替換匹配字符串的字符串
· count:匹配的最大替換次數(shù)
>>> re.sub(r'[1-9]\d{5}', ':zipcode', 'BIT100081 TSU100084')
'BIT:zipcode TSU:zipcode'
Re庫(kù)的另一種等價(jià)用法
regex = re.compile(pattern, flags=0)
將正則表達(dá)式的字符串形式編譯成正則表達(dá)式對(duì)象
`>>>regex = re.compile(r'[1-9]\d{5}')
函數(shù) | 說(shuō)明 |
---|---|
regex.search() | 在一個(gè)字符串中搜索匹配正則表達(dá)式的第一個(gè)位置,返回match對(duì)象 |
regex.match() | 從字符串開(kāi)始位置匹配 |
regex.findall() | 以列表類(lèi)型返回全部匹配的子串 |
regex.spilt() | 以匹配部分為分隔黄橘,并去掉 |
regex.finditer() | 搜索字符串兆览,返回匹配結(jié)果的迭代類(lèi)型 |
regex.sub() | 替換 |
Re庫(kù)的Match對(duì)象
match對(duì)象是一次匹配的結(jié)果,包含匹配的很多信息
>>> match = re.search(r'[1-9]\d{5}', 'BIT 100081')
>>> if match:
print(match.group(0))
100081
>>> type(match)
<class 're.Match'>
Match對(duì)象的屬性
屬性 | 說(shuō)明 |
---|---|
.string | 待匹配的文本 |
.re | 匹配時(shí)使用的patter對(duì)象(正則表達(dá)式) |
.pos | 正則表達(dá)式搜索文本的開(kāi)始位置 |
.endpos | 正則表達(dá)式搜索文本的結(jié)束位置 |
.group(0) | 獲得匹配后的字符串 |
.start() | 匹配字符串在原始字符串的開(kāi)始位置 |
.end() | 匹配字符串在原始字符串的結(jié)束位置 |
.span() | 返回(.start(), .end()) |
>>> import re
>>> m = re.search(r'[1-9]\d{5}', "BIT100081 TSU100084")
>>> m.string
'BIT100081 TSU100084'
>>> m.re
re.compile('[1-9]\\d{5}')
>>> m.pos
0
>>> m.endpos
19
>>> m.group(0)
'100081'
>>> m.start()
3
>>> m.end()
9
>>> m.span()
(3, 9)
Re庫(kù)的貪婪匹配和最小匹配
Re庫(kù)默認(rèn)采用貪婪匹配塞关,即輸出匹配最長(zhǎng)的子串
>>> match = re.search(r'PY.*N', 'PYANBNCNDN')
>>> match.group(0)
'PYANBNCNDN'
#PY.*N:以PY為口頭拓颓,N為結(jié)尾,*前任意字母無(wú)限擴(kuò)展
最小匹配操作符
操作符 | 說(shuō)明 |
---|---|
*? | 前一個(gè)字符0次或無(wú)限次擴(kuò)展描孟,最小匹配 |
+? | 前一個(gè)字符1次或無(wú)限次擴(kuò)展驶睦,最小匹配 |
?? | 前一個(gè)字符0次或1次擴(kuò)展砰左,最小匹配 |
{m,n} | 擴(kuò)展前一個(gè)字符m至n次(含n),最小匹配 |
>>> match = re.search(r'PY.*?N', 'PYANBNCNDN')
>>> match.group(0)
'PYAN'
爬取淘寶商品價(jià)格信息
import requests
import re
def getHTMLText(url): #獲得頁(yè)面
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def parsePage(ilt, html): #對(duì)獲得的頁(yè)面進(jìn)行解析
try:
plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt = re.findall(r'\"raw_titile\"\:\".*?\"',html)
for i in range(len(plt)):
price = eval(plt[i].spilt(':')[l])
title = eval(tlt[i].split(':')[l])
ilt.append([price, title])
except:
print("")
def printGoodsList(ilt):
tplt = "{:4}\t{:8}\t{:16}"
print(tplt.format("序號(hào)", "價(jià)格", "商品名稱(chēng)"))
count = 0
for g in ilt:
count = count + 1
print(tplt.format(count,g[0],g[1]))
def main():
goods = '書(shū)包' #爬取關(guān)鍵詞
depth = 2 #爬取深度
start_url = 'https://s.taobao.com/search?q=' + goods
infoList = [] #輸出結(jié)果
for i in range(depth):
try:
url = start_url + '&s=' + str(44*i)
html = getHTMLText(url)
parsePage(infoList, html)
except:
continue
printGoodsList(infoList)
main()