爬蟲處理——結(jié)構(gòu)化數(shù)據(jù)操作

爬蟲處理之結(jié)構(gòu)化數(shù)據(jù)操作

目錄清單

1.正則表達(dá)式提取數(shù)據(jù)

2.正則表達(dá)式案例操作

  1. 1.Xpath提取數(shù)據(jù)

  2. Xpath案例操作

  3. BeautifulSoup4提取數(shù)據(jù)

  4. BeautifulSoup4案例操作

章節(jié)內(nèi)容

1.關(guān)于數(shù)據(jù)

爬蟲程序,主要是運(yùn)行在網(wǎng)絡(luò)中進(jìn)行數(shù)據(jù)采集的一種計(jì)算機(jī)程序,正常的一個(gè)爬蟲采集數(shù)據(jù)的過程大致如下:

  • 訪問目標(biāo)服務(wù)器

  • 采集數(shù)據(jù)瞬项,獲取訪問url的數(shù)據(jù)

  • 根據(jù)需要篩選數(shù)據(jù)

  • 處理數(shù)據(jù),存儲到文件或者數(shù)據(jù)庫汇陆,等待下一步進(jìn)行數(shù)據(jù)分析或者數(shù)據(jù)展示

由于存在著不同的服務(wù)器和軟件應(yīng)用北秽,所以爬蟲獲取到的數(shù)據(jù)就會出現(xiàn)各種不同的表現(xiàn)形式,但是總體來說還是有規(guī)律的呢铆,有規(guī)律就可以被掌握的


首先贷屎,關(guān)于爬蟲處理的數(shù)據(jù)罢防,一般分為兩種數(shù)據(jù)

  • 非結(jié)構(gòu)化數(shù)據(jù):數(shù)據(jù)的內(nèi)容整體沒有固定的格式和語法規(guī)范

  • 結(jié)構(gòu)化數(shù)據(jù):數(shù)據(jù)的內(nèi)容有固定的語法規(guī)范,按照一定的結(jié)構(gòu)進(jìn)行組織管理

這兩種數(shù)據(jù)都分別表示什么樣的數(shù)據(jù)呢唉侄,分別應(yīng)該通過什么樣的方式進(jìn)行處理呢篙梢,這是爬蟲在采集完數(shù)據(jù)之后,針對數(shù)據(jù)進(jìn)行篩選必須要進(jìn)行的操作


接下來美旧,了解兩種不同的數(shù)據(jù)的表現(xiàn)形式

  • 非結(jié)構(gòu)化數(shù)據(jù)

無格式字符串?dāng)?shù)據(jù):用戶名渤滞、郵箱、賬號榴嗅、電話號碼妄呕、地址、電影名稱嗽测、評分绪励、評論肿孵、商品名稱等等

  • 結(jié)構(gòu)化數(shù)據(jù)

帶有一定的格式的數(shù)據(jù):HTML網(wǎng)頁文檔、XML網(wǎng)頁文檔疏魏、JSON等等


第三停做,對于不同的數(shù)據(jù),進(jìn)行有效數(shù)據(jù)篩選時(shí)大莫,應(yīng)該分別怎么進(jìn)行操作呢

  • 非結(jié)構(gòu)化數(shù)據(jù):由于沒有任何固定的格式蛉腌,只能根據(jù)字符出現(xiàn)的規(guī)律進(jìn)行動態(tài)匹配的方式來完成數(shù)據(jù)的提取:正則表達(dá)式

  • 結(jié)構(gòu)化數(shù)據(jù):由于數(shù)據(jù)本身存在一定的規(guī)律性只厘,可以通過針對這些規(guī)律的分析工具進(jìn)行數(shù)據(jù)的提壤哟浴:正則表達(dá)式、Xpath羔味、BeautifulSoup4河咽、select、css等等

2.正則表達(dá)式

正則表達(dá)式是一門單獨(dú)的技術(shù)赋元,在實(shí)際操作過程中由于它優(yōu)雅的字符匹配特性忘蟹,各種編程語言都陸續(xù)支持正則表達(dá)式的操作方式,Python中通過內(nèi)建模塊re進(jìn)行正則表達(dá)式的處理搁凸,大致按照如下三個(gè)步驟進(jìn)行數(shù)據(jù)的操作:

  • 確定源數(shù)據(jù):獲取整體數(shù)據(jù)

  • 按照目標(biāo)數(shù)據(jù)定義正則表達(dá)式匹配規(guī)則

  • 從整體數(shù)據(jù)中匹配符合要求的數(shù)據(jù)

正則表達(dá)式的處理媚值,最核心的是先掌握正則表達(dá)式的語法和匹配規(guī)則,根據(jù)實(shí)際操作的不同需要坪仇,正則表達(dá)式定義了不同的數(shù)據(jù)匹配方式

匹配規(guī)則 規(guī)則描述
\ 將下一個(gè)字符標(biāo)記為一個(gè)特殊字符、或一個(gè)原義字符垃你、或一個(gè)向后引用低矮、或一個(gè)八進(jìn)制轉(zhuǎn)義符赶促。例如,“n”匹配字符“n”∫氚“\n”匹配一個(gè)換行符。串行“\”匹配“\”而“(”則匹配“(”浪秘。
^ 匹配輸入字符串的開始位置评架。如果設(shè)置了RegExp對象的Multiline屬性,^也匹配“\n”或“\r”之后的位置锨亏。
$ 匹配輸入字符串的結(jié)束位置痴怨。如果設(shè)置了RegExp對象的Multiline屬性,$也匹配“\n”或“\r”之前的位置器予。
* 匹配前面的子表達(dá)式零次或多次浪藻。例如,zo能匹配“z”以及“zoo”乾翔。等價(jià)于{0,}爱葵。
+ 匹配前面的子表達(dá)式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”萌丈,但不能匹配“z”赞哗。+等價(jià)于{1,}。
? 匹配前面的子表達(dá)式零次或一次辆雾。例如肪笋,“do(es)?”可以匹配“does”或“does”中的“do”。?等價(jià)于{0,1}乾颁。
{n} n是一個(gè)非負(fù)整數(shù)涂乌。匹配確定的n次。例如英岭,“o{2}”不能匹配“Bob”中的“o”湾盒,但是能匹配“food”中的兩個(gè)o。
{n,} n是一個(gè)非負(fù)整數(shù)诅妹。至少匹配n次罚勾。例如,“o{2,}”不能匹配“Bob”中的“o”吭狡,但能匹配“foooood”中的所有o尖殃。“o{1,}”等價(jià)于“o+”划煮∷头幔“o{0,}”則等價(jià)于“o*”。
{n,m} m和n均為非負(fù)整數(shù)弛秋,其中n<=m器躏。最少匹配n次且最多匹配m次。例如蟹略,“o{1,3}”將匹配“fooooood”中的前三個(gè)o登失。“o{0,1}”等價(jià)于“o?”挖炬。請注意在逗號和兩個(gè)數(shù)之間不能有空格揽浙。
? 當(dāng)該字符緊跟在任何一個(gè)其他限制符(*,+,?,{n}意敛,{n,}馅巷,{n,m})后面時(shí),匹配模式是非貪婪的草姻。非貪婪模式盡可能少的匹配所搜索的字符串令杈,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字符串。例如碴倾,對于字符串“oooo”逗噩,“o+?”將匹配單個(gè)“o”掉丽,而“o+”將匹配所有“o”。
. 匹配除“\n”之外的任何單個(gè)字符异雁。要匹配包括“\n”在內(nèi)的任何字符捶障,請使用像“(.\n)”的模式。
(pattern) 匹配pattern并獲取這一匹配纲刀。所獲取的匹配可以從產(chǎn)生的Matches集合得到项炼,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性示绊。要匹配圓括號字符锭部,請使用“\(”或“\)”。
(?:pattern) 匹配pattern但不獲取匹配結(jié)果面褐,也就是說這是一個(gè)非獲取匹配拌禾,不進(jìn)行存儲供以后使用。這在使用或字符“( )”來組合一個(gè)模式的各個(gè)部分是很有用展哭。例如“industr(?:y ies)”就是一個(gè)比“industry industries”更簡略的表達(dá)式湃窍。
(?=pattern) 正向肯定預(yù)查,在任何匹配pattern的字符串開始處匹配查找字符串匪傍。這是一個(gè)非獲取匹配您市,也就是說,該匹配不需要獲取供以后使用役衡。例如茵休,“Windows(?=95 98 NT 2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”手蝎。預(yù)查不消耗字符榕莺,也就是說,在一個(gè)匹配發(fā)生后柑船,在最后一次匹配之后立即開始下一次匹配的搜索帽撑,而不是從包含預(yù)查的字符之后開始泼各。
(?!pattern) 正向否定預(yù)查鞍时,在任何不匹配pattern的字符串開始處匹配查找字符串。這是一個(gè)非獲取匹配扣蜻,也就是說逆巍,該匹配不需要獲取供以后使用。例如“Windows(?!95 98 NT 2000)”能匹配“Windows3.1”中的“Windows”莽使,但不能匹配“Windows2000”中的“Windows”锐极。預(yù)查不消耗字符,也就是說芳肌,在一個(gè)匹配發(fā)生后灵再,在最后一次匹配之后立即開始下一次匹配的搜索肋层,而不是從包含預(yù)查的字符之后開始
(?<=pattern) 反向肯定預(yù)查,與正向肯定預(yù)查類擬翎迁,只是方向相反栋猖。例如,“(?<=95 98 NT 2000)Windows”能匹配“2000Windows”中的“Windows”汪榔,但不能匹配“3.1Windows”中的“Windows”蒲拉。
(?x y 匹配x或y。例如痴腌,“z food”能匹配“z”或“food”雌团。“(z f)ood”則匹配“zood”或“food”士聪。
[xyz] 字符集合锦援。匹配所包含的任意一個(gè)字符。例如戚嗅,“[abc]”可以匹配“plain”中的“a”雨涛。
[^xyz] 負(fù)值字符集合。匹配未包含的任意字符懦胞。例如替久,“[^abc]”可以匹配“plain”中的“p”。
[a-z] 字符范圍躏尉。匹配指定范圍內(nèi)的任意字符蚯根。例如,“[a-z]”可以匹配“a”到“z”范圍內(nèi)的任意小寫字母字符胀糜。
[^a-z] 負(fù)值字符范圍颅拦。匹配任何不在指定范圍內(nèi)的任意字符。例如教藻,“[^a-z]”可以匹配任何不在“a”到“z”范圍內(nèi)的任意字符距帅。
\b 匹配一個(gè)單詞邊界,也就是指單詞和空格間的位置括堤。例如碌秸,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”悄窃。
\B 匹配非單詞邊界讥电。“er\B”能匹配“verb”中的“er”轧抗,但不能匹配“never”中的“er”恩敌。
\cx 匹配由x指明的控制字符。例如横媚,\cM匹配一個(gè)Control-M或回車符纠炮。x的值必須為A-Z或a-z之一月趟。否則,將c視為一個(gè)原義的“c”字符恢口。
\d 匹配一個(gè)數(shù)字字符狮斗。等價(jià)于[0-9]。
\D 匹配一個(gè)非數(shù)字字符弧蝇。等價(jià)于[^0-9]碳褒。
\f 匹配一個(gè)換頁符。等價(jià)于\x0c和\cL看疗。
\n 匹配一個(gè)換行符沙峻。等價(jià)于\x0a和\cJ。
\r 匹配一個(gè)回車符两芳。等價(jià)于\x0d和\cM摔寨。
\s 匹配任何空白字符,包括空格怖辆、制表符是复、換頁符等等。等價(jià)于[ \f\n\r\t\v]竖螃。
\S 匹配任何非空白字符淑廊。等價(jià)于[^ \f\n\r\t\v]。
\t 匹配一個(gè)制表符特咆。等價(jià)于\x09和\cI季惩。
\v 匹配一個(gè)垂直制表符。等價(jià)于\x0b和\cK腻格。
\w 匹配包括下劃線的任何單詞字符画拾。等價(jià)于“[A-Za-z0-9_]”。
\W 匹配任何非單詞字符菜职。等價(jià)于“[^A-Za-z0-9_]”青抛。
\xn 匹配n,其中n為十六進(jìn)制轉(zhuǎn)義值酬核。十六進(jìn)制轉(zhuǎn)義值必須為確定的兩個(gè)數(shù)字長蜜另。例如,“\x41”匹配“A”愁茁〔锨眨“\x041”則等價(jià)于“\x04&1”亭病。正則表達(dá)式中可以使用ASCII編碼鹅很。.
\num 匹配num,其中num是一個(gè)正整數(shù)罪帖。對所獲取的匹配的引用促煮。例如邮屁,“(.)\1”匹配兩個(gè)連續(xù)的相同字符。
\n 標(biāo)識一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用菠齿。如果\n之前至少n個(gè)獲取的子表達(dá)式佑吝,則n為向后引用。否則绳匀,如果n為八進(jìn)制數(shù)字(0-7)芋忿,則n為一個(gè)八進(jìn)制轉(zhuǎn)義值。
\nm 標(biāo)識一個(gè)八進(jìn)制轉(zhuǎn)義值或一個(gè)向后引用疾棵。如果\nm之前至少有nm個(gè)獲得子表達(dá)式戈钢,則nm為向后引用。如果\nm之前至少有n個(gè)獲取是尔,則n為一個(gè)后跟文字m的向后引用殉了。如果前面的條件都不滿足,若n和m均為八進(jìn)制數(shù)字(0-7)拟枚,則\nm將匹配八進(jìn)制轉(zhuǎn)義值nm薪铜。
\nml 如果n為八進(jìn)制數(shù)字(0-3),且m和l均為八進(jìn)制數(shù)字(0-7)恩溅,則匹配八進(jìn)制轉(zhuǎn)義值nml隔箍。
\un 匹配n,其中n是一個(gè)用四個(gè)十六進(jìn)制數(shù)字表示的Unicode字符脚乡。例如鞍恢,\u00A9匹配版權(quán)符號(?)。

3. python操作正則表達(dá)式

python內(nèi)置了re模塊每窖,可以很方便快捷的操作正則表達(dá)式語法完成字符串的查詢匹配操作行為帮掉,需要注意的是通過re操作正則表達(dá)式的兩種表現(xiàn)形式

第一種方式主要是通過compile()函數(shù)根據(jù)給定的正則表達(dá)式編譯生成正則匹配對象,通過正則匹配對象完成字符串的查詢匹配操作過程


import re

#定義正則表達(dá)式窒典,通過compile()函數(shù)編譯

pattern = re.compile('正則表達(dá)式')

#核心操作函數(shù)

# 1.起始位置匹配一次:僅從指定的起始位置進(jìn)行匹配(默認(rèn)開頭位置)

#匹配成功返回匹配到的字符串蟆炊,表示目標(biāo)字符串是該字符串開頭的

#匹配失敗返回None

value = pattern.match(string[, start[ , end]])

# 2.全文匹配一次:從指定的起始位置開始匹配(默認(rèn)開頭位置)

#陸續(xù)對字符串中的所有字符進(jìn)行匹配

#匹配成功返回匹配到的字符串,表示目標(biāo)字符串中包含該字符串

#匹配失敗返回None

value = pattern.search(string[, start[, end]])

# 3.全文匹配

#從目標(biāo)字符串中查詢所有符合匹配規(guī)則的字符瀑志,并存儲到一個(gè)列表中

#匹配結(jié)束返回列表涩搓,包含匹配到的數(shù)據(jù)

#沒有匹配到數(shù)據(jù)返回空列表,否則返回包含所有匹配數(shù)據(jù)的列表

value_list = pattern.findall(string[, start[, end]])

# 4.全文匹配獲取迭代器

#從目標(biāo)字符串中查詢所有符合匹配規(guī)則的字符劈猪,并存儲到一個(gè)迭代器中

value_iter = pattern.finditer(string[, start[, end]])

# 5.字符串切割:根據(jù)指定的正則表達(dá)式切割目標(biāo)字符串并返回切割后的列表

value_list = pattern.split(string)

# 6.字符串替換:根據(jù)指定的匹配規(guī)則昧甘,將string中符合的字符串替換為value值,count是替換次數(shù)战得,默認(rèn)全部替換

value_replace = pattern.sub(value, string[, count])

通過正則匹配到的值對象value充边,可以通過指定的函數(shù)輸出匹配到的數(shù)據(jù)的信息


#輸出匹配到的數(shù)據(jù)

value.group()

#輸出匹配到的第一組數(shù)據(jù)

value.group(1)

#輸出匹配的第n組數(shù)據(jù):前提條件是在正則表達(dá)式中使用圓括號進(jìn)行了n次分組

value.group(n)

#輸出匹配數(shù)據(jù)的索引范圍

value.span()

#輸出匹配的第n組數(shù)據(jù)的索引范圍

value.span(n)

#輸出匹配的第n組數(shù)據(jù)的索引開始位置

value.start(n)

#輸出匹配的第n組數(shù)據(jù)的索引結(jié)束位置

value.end(n)

注意的是:在使用正則表達(dá)式時(shí),貪婪模式和懶惰模式的操作行為可以精確的匹配數(shù)據(jù)

通常情況下,正則表達(dá)式模式是貪婪模式進(jìn)行匹配的浇冰,如果需要精確匹配的情況下贬媒,在正常正則表達(dá)式后面添加一個(gè)?匹配符號即可!


#定義目標(biāo)字符串

>>> s = "helelo world"

#編譯正則匹配對象:這里我們只是想得到: lel

>>> pattern = re.compile('l*l')

#進(jìn)行數(shù)據(jù)匹配操作

>>> r = re.compile('l.*l')

#展示數(shù)據(jù)

>>> r.search(s).group()

#展示得到的數(shù)據(jù)肘习,顯然匹配的數(shù)據(jù)中包含了其他數(shù)據(jù)

'lelo worl'

#那么际乘,下面這個(gè)例子,貌似更加實(shí)際

>>> html = "
i am div
i am p

i am div too
"

#定義匹配規(guī)則漂佩,只是想匹配div中包含的數(shù)據(jù)

>>> pattern = re.compile("
.*
")

#打印展示數(shù)據(jù)

>>> pattern.search(html).group()

#顯示的數(shù)據(jù)脖含,明顯包含了不需要的數(shù)據(jù),這是貪婪模式

'
i am div
i am p

i am div
'

#重新定義

>>> html = "
i am div
i am p

i am div too
"

#修改過的正則表達(dá)式

>>> pattern = re.compile("
.*?
")

#匹配得到數(shù)據(jù)

>>> pattern.search(html).group()

#顯示的數(shù)據(jù)投蝉,包含的數(shù)據(jù)器赞,就是精確匹配到的數(shù)據(jù)

'
i am div
'

正則表達(dá)式案例操作:百度圖片搜索下載


4. Xpath

Xpath原本是在可擴(kuò)展標(biāo)記語言XML中進(jìn)行數(shù)據(jù)查詢的一種描述語言,可以很方便的在XML文檔中查詢到具體的數(shù)據(jù)墓拜;后續(xù)再發(fā)展過程中港柜,對于標(biāo)記語言都有非常友好的支持,如超文本標(biāo)記語言HTML咳榜。


在操作Xpath之前夏醉,首先需要了解一些基礎(chǔ)的技術(shù)術(shù)語

下面是一段常見的HTML代碼


一級標(biāo)題



標(biāo)題

標(biāo)題

標(biāo)題

標(biāo)題

內(nèi)容

內(nèi)容

內(nèi)容

內(nèi)容

  • 根標(biāo)簽:在標(biāo)記語言中,處在最外層的一個(gè)標(biāo)簽就是根標(biāo)簽涌韩,根標(biāo)簽有且僅有一個(gè)畔柔,在上述代碼中\(zhòng)就是跟標(biāo)簽

  • 父標(biāo)簽:和子標(biāo)簽對應(yīng),內(nèi)部包含了其他元素?cái)?shù)據(jù)臣樱,該標(biāo)簽就是內(nèi)部標(biāo)簽的父標(biāo)簽靶擦,如\是\的父標(biāo)簽,\又是\的父標(biāo)簽雇毫,某些說法中玄捕,父標(biāo)簽的父標(biāo)簽..被稱為上級標(biāo)簽或則先代標(biāo)簽或者先輩標(biāo)簽

  • 子標(biāo)簽;和父標(biāo)簽對應(yīng)棚放,被包含的元素枚粘,就是外部元素的子標(biāo)簽,如\是\的子標(biāo)簽飘蚯,\標(biāo)簽是\的子標(biāo)簽馍迄,\是\的子標(biāo)簽;同樣的子標(biāo)簽的子標(biāo)簽局骤,也被稱為后代標(biāo)簽

  • 兄弟標(biāo)簽:兩個(gè)或者多個(gè)處在相同級別的標(biāo)簽攀圈,有相同的父標(biāo)簽,如\和\是兄弟標(biāo)簽峦甩,\和\是兄弟標(biāo)簽赘来,\中的兩個(gè)\是兄弟標(biāo)簽等等


  • Xpath描述語言的常見語法

和正則表達(dá)式相比較,Xpath使用最簡單的語法操作完成數(shù)據(jù)的查詢匹配操作

表達(dá)式 描述
nodename 選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)。
/ 從根節(jié)點(diǎn)選取撕捍。
// 從匹配選擇的當(dāng)前節(jié)點(diǎn)選擇文檔中的節(jié)點(diǎn),而不考慮它們的位置泣洞。
. 選取當(dāng)前節(jié)點(diǎn)忧风。
.. 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。
@ 選取屬性球凰。
* 匹配任何元素節(jié)點(diǎn)狮腿。
@* 匹配任何屬性節(jié)點(diǎn)。
node() 匹配任何類型的節(jié)點(diǎn)呕诉。
路徑表達(dá)式 結(jié)果
html 選取 html元素的所有子節(jié)點(diǎn)缘厢。
/html 選取根元素 html。注釋:假如路徑起始于正斜杠( / )甩挫,則此路徑始終代表到某元素的絕對路徑贴硫!
table/tr/td 選取屬于 table的子元素的所有 td元素。
//div | //table 選取所有的div或者table節(jié)點(diǎn)
//table 選取所有 table子元素伊者,而不管它們在文檔中的位置英遭。
html//div 選擇屬于html元素的后代的所有div元素,而不管它們位于 html之下的什么位置亦渗。
//@href 選取名為href的所有屬性挖诸。

通過如下的方式直接操作上面的文檔

路徑表達(dá)式 結(jié)果
html 選取 html元素的所有子節(jié)點(diǎn)。
/html 選取根元素 html法精。注釋:假如路徑起始于正斜杠( / )多律,則此路徑始終代表到某元素的絕對路徑!
table/tr/td 選取屬于 table的子元素的所有 td元素搂蜓。
//div | //table 選取所有的div或者table節(jié)點(diǎn)
//table 選取所有 table子元素狼荞,而不管它們在文檔中的位置。
html//div 選擇屬于html元素的后代的所有div元素帮碰,而不管它們位于 html之下的什么位置粘秆。
//@href 選取名為href的所有屬性。

標(biāo)簽條件篩選查詢匹配

路徑表達(dá)式 結(jié)果
//table/tr[1] 選取屬于table子元素的第一個(gè) tr元素收毫。
//table/tr[last()] 選取屬于 table子元素的最后一個(gè) tr元素攻走。
//table/tr[last()-1] 選取屬于 table子元素的倒數(shù)第二個(gè) tr元素。
//table/tr[position()<3] 選取最前面的兩個(gè)屬于 table元素的子元素的tr元素此再。
//td[@width] 選取所有擁有名為 width的屬性的 td元素昔搂。
//td[@width='100'] 選取所有 td元素,且這些元素?fù)碛袑傩詗idth并且值為100输拇。
//tr//td[span>10000] 選取tr元素的所有td子元素摘符,并且其中的span元素的值須大于10000。

同樣,Xpath支持?jǐn)?shù)據(jù)運(yùn)算操作

運(yùn)算符 描述 實(shí)例 返回值
+ 加法 6 + 4 10
- 減法 6 - 4 2
* 乘法 6 * 4 24
div 除法 8 div 4 2
= 等于 price=9.80 如果 price是 9.80逛裤,則返回 true瘩绒。如果 price是 9.90,則返回 false带族。
!= 不等于 price!=9.80 如果 price是 9.90锁荔,則返回 true。如果 price是9.80蝙砌,則返回 false阳堕。
< 小于 price<9.80 如果 price是 9.00,則返回 true择克。如果 price是 9.90恬总,則返回 false。
<= 小于或等于 price<=9.80 如果 price是 9.00肚邢,則返回 true壹堰。如果 price是 9.90,則返回 false骡湖。
> 大于 price>9.80 如果 price是 9.90缀旁,則返回 true。如果 price是 9.80勺鸦,則返回 false并巍。
>= 大于或等于 price>=9.80 如果 price是 9.90,則返回 true换途。如果 price是 9.70懊渡,則返回 false。
or price=9.80 or price=9.70 如果 price是 9.80军拟,則返回 true剃执。如果 price是 9.50,則返回 false懈息。
and price>9.00 and price<9.90 如果 price是 9.80肾档,則返回 true。如果 price是 8.50辫继,則返回 false怒见。
mod 計(jì)算除法的余數(shù) 5 mod 2 1

xpath在瀏覽器中進(jìn)行測試時(shí),可以給谷歌瀏覽器安裝一個(gè)插件Xpath Helper插件姑宽;就可以直接在瀏覽器中通過xpath語法來完成對數(shù)據(jù)的匹配測試

測試通過的xpath語法遣耍,就可以直接在程序中使用了!


5.python操作Xpath

python第三方模塊lxml可以對Xpath有友好的支持炮车,lxml是C實(shí)現(xiàn)的一種高性能python用于HTML/XML的解析模塊舵变,可以通過Xpath語法在html文檔數(shù)據(jù)中進(jìn)行指定表達(dá)式數(shù)據(jù)的索引查詢

*簡單etree操作


# -*- coding:utf-8 -*-

from lxml import etree

#模擬得到爬蟲數(shù)據(jù)

content = """

個(gè)人簡介



姓名:某某某


住址:中國 鄉(xiāng)下


座右銘:豈能盡如人意酣溃,但求無愧于心


"""

#轉(zhuǎn)換成html數(shù)據(jù)

# html = etree.parse("index.html")#從文件中直接加載html數(shù)據(jù)

html = etree.HTML(content)#通過etree.HTML()函數(shù)將字符串轉(zhuǎn)換成HTML文檔對象

print dir(html)#查看文檔對象的所有函數(shù)

print html.getchildren()#查看文檔對象根節(jié)點(diǎn)的所有子節(jié)點(diǎn)

#轉(zhuǎn)換成字符數(shù)據(jù)

str_html = etree.tostring(html)#將HTML文檔對象轉(zhuǎn)換成字符串

print type(str_html)#查看輸出類型

print str_html#查看輸出數(shù)據(jù)

  • xpath操作

# -*- coding:utf-8 -*-

from lxml import etree

#模擬得到爬蟲數(shù)據(jù)

content = u"""

個(gè)人簡介



姓名:某某某


住址:中國 鄉(xiāng)下


座右銘:豈能盡如人意,但求無愧于心


"""

#將爬取到的數(shù)據(jù)轉(zhuǎn)換成HTML文檔

html = etree.HTML(content)

#查詢所有的p標(biāo)簽

p_x = html.xpath("http://p")

print(p_x)

#查詢所有Name屬性的值

v_attr_name= html.xpath("http://@name")

print(v_attr_name)

#查詢所有包含name屬性的標(biāo)簽

e_attr_name = html.xpath("http://*[@name]")

print(e_attr_name)

#查詢所有包含name屬性纪隙,并且name屬性值為desc的標(biāo)簽

e_v_attr_name = html.xpath("http://*[@name='desc']")

print(e_v_attr_name)

#查詢所有p標(biāo)簽的文本內(nèi)容,不包含子標(biāo)簽

p_t = html.xpath("http://p")

for p in p_t:

print (p.text)

#查詢多個(gè)p標(biāo)簽下的所有文本內(nèi)容赊豌,包含子標(biāo)簽中的文本內(nèi)容

p_m_t = html.xpath("http://p")

for p2 in p_m_t:

print(p2.xpath("string(.)"))

案例操作:爬蟲智聯(lián)招聘中前10頁的某個(gè)工作崗位名稱、薪水绵咱、公司信息


6. BeautifulSoup4

BeautifulSoup也是一種非常優(yōu)雅的專門用于進(jìn)行HTML/XML數(shù)據(jù)解析的一種描述語言碘饼,可以很好的分析和篩選HTML/XML這樣的標(biāo)記文檔中的指定規(guī)則數(shù)據(jù)

在數(shù)據(jù)篩選過程中其基礎(chǔ)技術(shù)是通過封裝HTML DOM樹實(shí)現(xiàn)的一種DOM操作,通過加載網(wǎng)頁文檔對象的形式麸拄,從文檔對象模型中獲取目標(biāo)數(shù)據(jù)

BeautifulSoup操作簡單易于上手派昧,在很多對于數(shù)據(jù)篩選性能要求并不是特別苛刻的項(xiàng)目中經(jīng)常使用黔姜,目前市場流行的操作版本是BeautifulSoup4拢切,經(jīng)常稱BS4

Xpath和BeautifulSoup

Xpath和BeautifulSoup都是基于DOM的一種操作模式

不同點(diǎn)在于加載文檔對象模型DOM時(shí)出現(xiàn)的文檔節(jié)點(diǎn)遍歷查詢操作過程,Xpath在進(jìn)行遍歷操作時(shí)針對描述語言指定的語法結(jié)構(gòu)進(jìn)行局部DOM對象樹的遍歷得到具體的數(shù)據(jù)秆吵,但是BS4在操作過程中淮椰,會將整個(gè)文檔樹進(jìn)行加載然后進(jìn)行查詢匹配操作,使用過程中消耗資源較多纳寂,處理性能相對Xpath較低

那么為什么要用BS4呢主穗?因?yàn)椋形撸銐蚝唵?

描述語言 處理效率 上手程度
正則表達(dá)式 效率非常高 困難
Xpath 效率很高 正常
BS4 效率較高 簡單

BS4本身是一種對描述語言進(jìn)行封裝的函數(shù)操作模塊忽媒,通過提供面向?qū)ο蟮牟僮鞣绞綄⑽臋n對象中的各種節(jié)點(diǎn)、標(biāo)簽腋粥、屬性晦雨、內(nèi)容等等都封裝成了python中對象的屬性,在查詢操作過程中隘冲,通過調(diào)用指定的函數(shù)直接進(jìn)行數(shù)據(jù) 匹配檢索操作,非常的簡單非常的靈活。

一般BS4將HTML文檔對象會轉(zhuǎn)換成如下四種類型組合的文檔樹

  • Tag:標(biāo)簽對象

  • NavigableString:字符內(nèi)容操作對象

  • BeautifulSoup:文檔對象

  • Comment:特殊類型的NavigableString

說道這里航夺,其實(shí)都是太多的理論性語法划提,BS4不同于正則和Xpath,沒有什么基礎(chǔ)語法結(jié)構(gòu)罗珍,它封裝的對象以及對象的屬性操作洽腺,才是BS4不同凡響的核心價(jià)值

let's上干貨

7. python操作BeautifulSoup4

python中對于BeautifulSoup的支持,通過安裝第三方模塊來發(fā)揮它最好的操作


$ pip install beautifulsoup4

*入門第一彈:了解BeautifulSoup4


# coding:utf-8

#引入解析模塊BS4

from bs4 import BeautifulSoup

#從文件中加載html網(wǎng)頁覆旱,指定HTML解析器使用lxml

#默認(rèn)不指定的情況下已脓,BS4會自動匹配當(dāng)前系統(tǒng)中最優(yōu)先的解析器

soup = BeautifulSoup(open("index.html"), "lxml")

#如果是爬蟲獲取到的字符數(shù)據(jù),直接交給BS4就OK拉

# soup = BeatufulSoup(spider_content, "lxml")

#打印BeautifulSoup文檔對象通殃,得到的是文檔樹內(nèi)容

print(soup)

#打印類型:

print(type(soup))

*入門第二彈:操作標(biāo)簽度液、屬性厕宗、內(nèi)容


# coding:utf-8

from bs4 import BeautifulSoup

#得到構(gòu)建的文檔對象

soup = BeautifulSoup(open("index.html"), "lxml")

# Tag操作

# 1.獲取標(biāo)簽

print(soup.title) #
print(soup.p) #
姓名:大牧

#只返回第一個(gè)匹配到的標(biāo)簽對象

print(soup.span) # 大牧

# 2.獲取標(biāo)簽的屬性

print(soup.p.attrs) # {}:得到屬性和值的字典

print(soup.span.attrs) # {'id': 'name'}:得到屬性和值的字典

print(soup.span['id']) # name:得到指定屬性的值

soup.span['id'] = "real_name"

print(soup.span['id']) # real_name :可以方便的在BS4中直接對文檔進(jìn)行修改

# 3.獲取標(biāo)簽的內(nèi)容

print(soup.head.string) #文章標(biāo)題:如果標(biāo)簽中只有一個(gè)子標(biāo)簽~返回子標(biāo)簽中的文本內(nèi)容

print(soup.p.string) # None:如果標(biāo)簽中有多個(gè)子標(biāo)簽,返回None

print(soup.span.string) #大牧:直接返回包含的文本內(nèi)容

*入門第三彈:操作子節(jié)點(diǎn)


# coding:utf-8

#引入BS4操作模塊

from bs4 import BeautifulSoup

#加載網(wǎng)頁文檔堕担,構(gòu)建文檔對象

soup = BeautifulSoup(open("index.html"), "lxml")

print(dir(soup))

print(soup.contents)#得到文檔對象中所有子節(jié)點(diǎn)

print(soup.div.contents)#得到匹配到的第一個(gè)div的子節(jié)點(diǎn)列表

print(soup.div.children)#得到匹配到的第一個(gè)div的子節(jié)點(diǎn)列表迭代器

# for e1 in soup.div.children:

#    print("-->", e1)

print(soup.div.descendants)#得到匹配到的第一個(gè)div的子節(jié)點(diǎn)迭代器,所有后代節(jié)點(diǎn)單獨(dú)一個(gè)一個(gè)列出

# for e2 in soup.div.descendants:

#    print("==>", e2)

*入門第四彈:面向?qū)ο蟮腄OM匹配


# coding:utf-8

#引入BS4模塊

from bs4 import BeautifulSoup

#加載文檔對象

soup = BeautifulSoup(open("../index.html"), "lxml")

# DOM文檔樹查詢

#核心函數(shù)~請對比javasript dom結(jié)構(gòu)了解它的方法

#如:findAllPrevious()/findAllNext()/findAll()/findPrevious()/findNext()等等

# findAll()為例

# 1.查詢指定的字符串

res1 = soup.findAll("p")#查詢所有包含p字符的標(biāo)簽

print(res1)

# 2.正則表達(dá)式

import re

res2 = soup.findAll(re.compile(r"d+"))#查詢所有包含d字符的標(biāo)簽

print(res2)

# 3.列表:選擇

res3 = soup.findAll(["div", "h1"])#查詢所有的div或者h(yuǎn)1標(biāo)簽

print(res3)

# 4.關(guān)鍵字參數(shù)

res4 = soup.findAll(id="name")#查詢屬性為id="name"的標(biāo)簽

print(res4)

# 5.內(nèi)容匹配

res5 = soup.findAll(text=u"男")#直接匹配內(nèi)容中的字符已慢,必須保證精確匹配

print(res5)

res6 = soup.findAll(text=[u"文章標(biāo)題", u"大牧"])#查詢包含精確內(nèi)容的所有的標(biāo)簽

print(res6)

res7 = soup.findAll(text=re.compile(u"大+"))#通過正則表達(dá)式進(jìn)行模糊匹配

print(res7)

*入門第五彈:又見CSS


# coding:utf-8

#引入BS模塊

from bs4 import BeautifulSoup

#加載網(wǎng)頁構(gòu)建文檔對象

soup = BeautifulSoup(open("index.html"), "lxml")

# 1. CSS標(biāo)簽選擇器:根據(jù)標(biāo)簽名稱查詢標(biāo)簽對象

res1 = soup.select("span")

print(res1)

# 2. CSS ID選擇器:根據(jù)ID查詢標(biāo)簽對象

res2 = soup.select("#gender")

print(res2)

# 3. CSS類選擇器:根據(jù)class屬性查詢標(biāo)簽對象

res3 = soup.select(".intro")

print(res3)

# 4. CSS屬性選擇器

res41 = soup.select("span[id]")

print(res41)

res42 = soup.select("span[id='gender']")

print(res42)

# 5. CSS包含選擇器

res5 = soup.select("p span#name")

print(res5)

# 6.得到標(biāo)簽內(nèi)容

res6 = soup.select("p > span.intro")

print(res6[0].string)

print(res6[0].getText())

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市霹购,隨后出現(xiàn)的幾起案子佑惠,更是在濱河造成了極大的恐慌,老刑警劉巖齐疙,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膜楷,死亡現(xiàn)場離奇詭異,居然都是意外死亡贞奋,警方通過查閱死者的電腦和手機(jī)赌厅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轿塔,“玉大人特愿,你說我怎么就攤上這事」寸裕” “怎么了揍障?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長俩由。 經(jīng)常有香客問我毒嫡,道長,這世上最難降的妖魔是什么幻梯? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任兜畸,我火速辦了婚禮,結(jié)果婚禮上礼旅,老公的妹妹穿的比我還像新娘膳叨。我一直安慰自己,他們只是感情好痘系,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布菲嘴。 她就那樣靜靜地躺著,像睡著了一般汰翠。 火紅的嫁衣襯著肌膚如雪龄坪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天复唤,我揣著相機(jī)與錄音健田,去河邊找鬼。 笑死佛纫,一個(gè)胖子當(dāng)著我的面吹牛妓局,可吹牛的內(nèi)容都是我干的总放。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼好爬,長吁一口氣:“原來是場噩夢啊……” “哼局雄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起存炮,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤炬搭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后穆桂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宫盔,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年享完,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灼芭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驼侠,死狀恐怖姿鸿,靈堂內(nèi)的尸體忽然破棺而出谆吴,到底是詐尸還是另有隱情倒源,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布句狼,位于F島的核電站笋熬,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏腻菇。R本人自食惡果不足惜胳螟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望筹吐。 院中可真熱鬧糖耸,春花似錦、人聲如沸丘薛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洋侨。三九已至舍扰,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間希坚,已是汗流浹背边苹。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裁僧,地道東北人个束。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓慕购,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茬底。 傳聞我的和親對象是個(gè)殘疾皇子脓钾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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