Lunr.js是個(gè)用于瀏覽器的輕量級 JavaScript 全文搜索引擎。它為JSON文檔建立索引,并提供一個(gè)簡單的搜索界面來檢索與文本查詢最匹配的文檔對于一些小型的博客、開發(fā)者文檔或 Wiki 網(wǎng)站來說,完全可以通過它實(shí)現(xiàn)站內(nèi)離線搜索:
對于已經(jīng)將所有數(shù)據(jù)存儲在客戶端中的Web應(yīng)用程序,也能夠在客戶端上搜索該數(shù)據(jù)也是很有意義的。這樣可以節(jié)省在服務(wù)器上添加額外的壓縮服務(wù)。本地搜索索引將更快,沒有網(wǎng)絡(luò)開銷,并且即使沒有網(wǎng)絡(luò)連接也將保持可用。
目前Github上star數(shù)6.6k
https://github.com/olivernn/lunr.js
var idx = lunr(function () {
this.field('title')
this.field('body')
this.add({
"title": "Twelfth-Night",
"body": "If music be the food of love, play on: Give me excess of it…",
"author": "William Shakespeare",
"id": "1"
})
})
然后再像下面這樣
idx.search("love")
這將返回一個(gè)匹配文檔列表,其中包含與搜索查詢的匹配程度以及與該匹配相關(guān)的任何關(guān)聯(lián)元數(shù)據(jù)的分?jǐn)?shù):
[
{
"ref": "1",
"score": 0.3535533905932737,
"matchData": {
"metadata": {
"love": {
"body": {}
}
}
}
}
]
只需在要使用它的頁面中包含lunr.js源文件。所有現(xiàn)代瀏覽器均支持Lunr.js。
npm install lunr
(翻譯或不夠準(zhǔn)確)
在之前的文章中介紹過另一個(gè)全文搜索庫FlexSearch.js,感興趣的小伙伴也可以去看一看介紹,在這里也提前祝大家新年快樂,萬事如意,身體健康!
html_doc = """
<html><head><title>index</title></head>
<body>
<p class="title"><b>首頁</b></p>
<p class="main">我常用的網(wǎng)站
<a href="https://www.google.com" class="website" id="google">Google</a>
<a href="https://www.baidu.com" class="website" id="baidu">Baidu</a>
<a href="https://cn.bing.com" class="website" id="bing">Bing</a>
</p>
<div><!--這是注釋內(nèi)容--></div>
<p class="content1">...</p>
<p class="content2">...</p>
</body>
"""
soup = BeautifulSoup(html_doc, "lxml")
正式講解搜索文檔之前,我們有必要了解下 Beautiful Soup 的過濾器,這些過濾器在整個(gè)搜索的 API 中都有所體現(xiàn),他們可以被用在 TAG 的 name 中,屬性中,字符串中或他們的混合中。聽起來有點(diǎn)繞是么,看幾個(gè)例子就懂了。
1、根據(jù) TAG 的 name 來查找標(biāo)簽,下面的例子會查找文檔中的所有 b 標(biāo)簽。同時(shí)要注意統(tǒng)一傳入 Unicode 編碼以避免 Beautiful Soup 解析編碼出錯。
# demo 1
tags = soup.find_all('b')
print(tags)
#輸出結(jié)果
[<b>首頁</b>]
2、如果傳入正則表達(dá)式作為參數(shù),那么 Beautiful Soup 會通過正則表達(dá)式的 match() 來匹配內(nèi)容。
# demo 2
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
#輸出結(jié)果
body
b
3、如果傳入列表參數(shù),那么 Beautiful Soup 會將與列表中任意一個(gè)元素匹配的內(nèi)容返回。
# demo 3
for tag in soup.find_all(['a', 'b']):
print(tag)
#輸出結(jié)果
<b>首頁</b>
<a class="website" href="https://www.google.com" id="google">Google</a>
<a class="website" href="https://www.baidu.com" id="baidu">Baidu</a>
<a class="website" href="https://cn.bing.com" id="bing">Bing</a>
4、True 可以匹配任何值,下面的例子是查找所有的 TAG 但不會返回字符串。
# demo 4
for tag in soup.find_all(True):
print(tag.name, end=', ')
#輸出結(jié)果
html, head, title, body, p, b, p, a, a, a, div, p, p,
5、方法。我們可以定義一個(gè)方法,該方法只接受一個(gè)參數(shù),若該方法返回 True 則表示當(dāng)前元素匹配并且被找到,返回 False 意味著沒找到。下面的例子展示了查找所有同時(shí)包含 class 屬性和 id 屬性的節(jié)點(diǎn)。
# demo 5
def has_id_class(tag):
return tag.has_attr('id') and tag.has_attr('class')
tags = soup.find_all(has_id_class)
for tag in tags:
print(tag)
#輸出結(jié)果
<a class="website" href="https://www.google.com" id="google">Google</a>
<a class="website" href="https://www.baidu.com" id="baidu">Baidu</a>
<a class="website" href="https://cn.bing.com" id="bing">Bing</a>
大部分情況字符串過濾器就可以滿足我們的需求,外加這個(gè)神奇的方法過濾器,我們就可以實(shí)現(xiàn)各種自定義需求了。
該函數(shù)搜索當(dāng)前節(jié)點(diǎn)下的所有子節(jié)點(diǎn),其簽名如下find_all( name , attrs , recursive , text , **kwargs )。我們可以傳入指定 TAG 的 name 來查找節(jié)點(diǎn),上面已經(jīng)舉過例子了,這里不再贅述。我們來看幾個(gè)其他的用法。
1、如果我們轉(zhuǎn)入 find_all() 函數(shù)不是搜索內(nèi)置的參數(shù)名,那么搜索是就會將該參數(shù)對應(yīng)到屬性上去。下文的例子表示查找 id 為 google 的節(jié)點(diǎn)。
搜索指定名字的屬性時(shí)可以使用的參數(shù)值包括:字符串,正則表達(dá)式,列表,True。也就是我們上文介紹過的過濾器。
# demo 6
tags = soup.find_all(id='google')
print(tags[0]['href'])
for tag in soup.find_all(id=True): # 查找所有包含 id 屬性的 TAG
print(tag['href'])
#輸出結(jié)果
https://www.google.com
https://www.google.com
https://www.baidu.com
https://cn.bing.com
2、按照 CSS 類名搜索,但是鏢師 CSS 的關(guān)鍵字 class 在 Python 中是內(nèi)置關(guān)鍵字,從 Beautiful Soup 4.1.1 版本開始,可以通過 class_ 參數(shù)搜索有指定 CSS 類名的 TAG:
class_ 參數(shù)同樣接受不同類型的過濾器:字符串,正則表達(dá)式,方法,True。
# demo 7
tags = soup.find_all("a", class_="website")
for tag in tags:
print(tag['href'])
def has_seven_characters(css_class):
return css_class is not None and len(css_class) == 7
for tag in soup.find_all(class_=has_seven_characters):
print(tag['id'])
#輸出結(jié)果
https://www.google.com
https://www.baidu.com
https://cn.bing.com
google
baidu
bing
同時(shí),因?yàn)?CSS 可以有多個(gè)值,所以我們可以分別搜索 CSS 中的每個(gè)值。
# demo 8
css_soup = BeautifulSoup('<p class="body strikeout"></p>', 'lxml')
tags = css_soup.find_all("p", class_="strikeout")
print(tags)
#輸出結(jié)果
[<p class="body strikeout"></p>]
3、不僅可以按照標(biāo)簽和 CSS 來搜索整個(gè)文檔,還可以使用 text 再按照內(nèi)容來搜索。同時(shí) text 還可以配合其他屬性一起來完成搜索任務(wù)。
# demo 9
tags = soup.find_all(text="Google")
print("google : ", tags)
tags = soup.find_all(text=["Baidu", "Bing"])
print("baidu & bing : ", tags)
tags = soup.find_all('a', text="Google")
print("a[text=google] : ", tags)
#輸出結(jié)果
google : ['Google']
baidu & bing : ['Baidu', 'Bing']
a[text=google] : [<a class="website" href="https://www.google.com" id="google">Google</a>]
4、限制返回?cái)?shù)量
有時(shí)候文檔樹過于龐大,我們不想查查找整棵樹,只想查找指定數(shù)量的節(jié)點(diǎn),或者只想查找子節(jié)點(diǎn),而不想查找孫子節(jié)點(diǎn),指定 limit 或者 recursive 參數(shù)即可。
# demo 10
tag = soup.find_all("a", limit=1)
print(tag)
tags = soup.find_all("p", recursive=False)
print(tags)
#輸出結(jié)果
[<a class="website" href="https://www.google.com" id="google">Google</a>]
[]
因?yàn)樵搶ο蟮膬鹤庸?jié)點(diǎn)沒有 p 標(biāo)簽,所以返回的是空列表。
該函數(shù)只會返回一個(gè)結(jié)果,與 find_all(some_args, limit=1) 是等價(jià)的,唯一的區(qū)別就是該函數(shù)直接返回結(jié)果,而 find_all() 函數(shù)返回包含一個(gè)結(jié)果的列表。另外 find_all() 方法沒有找到目標(biāo)是返回空列表, find() 方法找不到目標(biāo)時(shí),返回 None。除此之外使用上沒有其他差別。
除了 find_all() 和 find() 外,Beautiful Soup 中還有 10 個(gè)用于搜索的 API,其中中五個(gè)用的是與 find_all() 相同的搜索參數(shù),另外 5 個(gè)與 find() 方法的搜索參數(shù)類似,區(qū)別僅是它們搜索文檔的范圍不同。
find_parents() 和 find_parent() 用來搜索當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。
find_next_siblings() 和 find_next_sibling() 對在當(dāng)前節(jié)點(diǎn)后面解析的所有兄弟節(jié)點(diǎn)進(jìn)行迭代。
find_previous_siblings() 和 find_previous_sibling() 對在當(dāng)前節(jié)點(diǎn)前面解析的所有兄弟節(jié)點(diǎn)進(jìn)行迭代。
find_all_next() 和 find_next() 對當(dāng)前節(jié)點(diǎn)之后的 TAG 和字符串進(jìn)行迭代。
find_all_previous() 和 find_previous() 對當(dāng)前節(jié)點(diǎn)之前的 TAG 和字符串進(jìn)行迭代。
以上五組函數(shù)的區(qū)別僅僅是前者返回一個(gè)所有符合搜索條件的節(jié)點(diǎn)列表,而后者只返回第一個(gè)符合搜索條件的節(jié)點(diǎn)。
因?yàn)檫@ 10 個(gè) API 的使用和 find_all() 與 find() 大同小異,所有i這里不再舉例,讀者可以自己探索。
在 Tag 或 BeautifulSoup 對象的 .select() 方法中傳入字符串參數(shù)即可使用 CSS 選擇器的語法找到 TAG。
1、通過某個(gè)標(biāo)簽逐層查找。
# demo 11
tags = soup.select("body a")
for tag in tags:
print(tag['href'])
#輸出結(jié)果
https://www.google.com
https://www.baidu.com
https://cn.bing.com
2、查找某個(gè)標(biāo)簽下的直接子標(biāo)簽
# demo 12
tags = soup.select("p > a")
print(tags)
tags = soup.select("p > #google")
print(tags)
#輸出結(jié)果
[<a class="website" href="https://www.google.com" id="google">Google</a>, <a class="website" href="https://www.baidu.com" id="baidu">Baidu</a>, <a class="website" href="https://cn.bing.com" id="bing">Bing</a>]
[<a class="website" href="https://www.google.com" id="google">Google</a>]
3、通過 CSS 類名直接查找
# demo 13
tags = soup.select(".website")
for tag in tags:
print(tag.string)
#輸出結(jié)果
Google
Baidu
Bing
4、通過標(biāo)簽的 id 屬性查找
# demo 14
tags = soup.select("#google")
print(tags)
#輸出結(jié)果
[<a class="website" href="https://www.google.com" id="google">Google</a>]
5、通過屬性的值來查找
擊查看效果動圖
知識點(diǎn):移動端適配,跨域jsonp處理,
原生javascript封裝jsonp,ajax與跨域原理講解,
圖片等比縮放算法, 瀑布流實(shí)現(xiàn)原理講解,
百度圖片內(nèi)部請求入口.JavaScript編程原理與事務(wù)處理思考
PS:javascript不是做幾個(gè)特效就可以說學(xué)會了的,做簡單特效其實(shí)只是javascript的一個(gè)最簡單的運(yùn)用,群內(nèi)很多伙伴都說現(xiàn)在找工作找不到,什么都學(xué)了,連面試機(jī)會都沒有,這不是所謂的前端需求滿了,而是很多伙伴學(xué)的并不扎實(shí),很多基礎(chǔ)的東西都沒有學(xué)好,作為很多框架和插件的基礎(chǔ),原生javascript一定是非常重要的,這次分享,就是做了一個(gè)對原生javascript稍微深層次的利用,有什么不懂得或者不足的,歡迎指正!附上完整源碼/視頻以及注釋!
如果想要更多的企業(yè)求職加分項(xiàng)目,案例,可以來一下我的前端群216634437,每天都會精挑細(xì)選一個(gè)特效,項(xiàng)目出來詳細(xì)講解,分享!
HTML/javascript移動端百度圖片搜索源碼:
需要文檔版源碼來我的前端群216634437,已上傳到群文件
移動端javascript百度圖片搜索視頻:原生JavaScript實(shí)現(xiàn)移動端百度圖片搜索
頭條號里有許多web前端學(xué)習(xí)視頻,企業(yè)常用特效/案例/項(xiàng)目,敬請關(guān)注!
下期群內(nèi)分享:
想思路思路思路!!!!
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。