python網(wǎng)絡(luò)爬蟲(chóng)學(xué)習(xí)筆記

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&amp;tpl=mn&amp;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>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必讀</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意見(jiàn)反饋</a>&nbsp;京ICP證030173號(hào)&nbsp; <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

簡(jiǎn)潔表達(dá)一組字符串的表達(dá)式:
image.png

正則表達(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()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末场航,一起剝皮案震驚了整個(gè)濱河市缠导,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溉痢,老刑警劉巖僻造,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異孩饼,居然都是意外死亡髓削,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)镀娶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)立膛,“玉大人,你說(shuō)我怎么就攤上這事梯码”Ρ茫” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵轩娶,是天一觀的道長(zhǎng)儿奶。 經(jīng)常有香客問(wèn)我,道長(zhǎng)鳄抒,這世上最難降的妖魔是什么闯捎? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮许溅,結(jié)果婚禮上隙券,老公的妹妹穿的比我還像新娘。我一直安慰自己闹司,他們只是感情好娱仔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著游桩,像睡著了一般牲迫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上借卧,一...
    開(kāi)封第一講書(shū)人閱讀 49,850評(píng)論 1 290
  • 那天盹憎,我揣著相機(jī)與錄音,去河邊找鬼铐刘。 笑死陪每,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播檩禾,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼挂签,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了盼产?” 一聲冷哼從身側(cè)響起饵婆,我...
    開(kāi)封第一講書(shū)人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎戏售,沒(méi)想到半個(gè)月后侨核,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灌灾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年搓译,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锋喜。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡些己,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出跑芳,到底是詐尸還是另有隱情,我是刑警寧澤直颅,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布博个,位于F島的核電站,受9級(jí)特大地震影響功偿,放射性物質(zhì)發(fā)生泄漏盆佣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一械荷、第九天 我趴在偏房一處隱蔽的房頂上張望共耍。 院中可真熱鬧,春花似錦吨瞎、人聲如沸痹兜。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)字旭。三九已至,卻和暖如春崖叫,著一層夾襖步出監(jiān)牢的瞬間遗淳,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工心傀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屈暗,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像养叛,于是被迫代替她去往敵國(guó)和親种呐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容