Lunr.js是个用于浏览器的轻量级 JavaScript 全文搜索引擎。它为JSON文档建立索引,并提供一个简单的搜索界面来检索与文本查询最匹配的文档对于一些小型的博客、开发者文档或 Wiki 网站来说,完全可以通过它实现站内离线搜索:
对于已经将所有数据存储在客户端中的Web应用程序,也能够在客户端上搜索该数据也是很有意义的。这样可以节省在服务器上添加额外的压缩服务。本地搜索索引将更快,没有网络开销,并且即使没有网络连接也将保持可用。
目前Github上star数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")
这将返回一个匹配文档列表,其中包含与搜索查询的匹配程度以及与该匹配相关的任何关联元数据的分数:
[
{
"ref": "1",
"score": 0.3535533905932737,
"matchData": {
"metadata": {
"love": {
"body": {}
}
}
}
}
]
只需在要使用它的页面中包含lunr.js源文件。所有现代浏览器均支持Lunr.js。
npm install lunr
(翻译或不够准确)
在之前的文章中介绍过另一个全文搜索库FlexSearch.js,感兴趣的小伙伴也可以去看一看介绍,在这里也提前祝大家新年快乐,万事如意,身体健康!
html_doc = """
<html><head><title>index</title></head>
<body>
<p class="title"><b>首页</b></p>
<p class="main">我常用的网站
<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><!--这是注释内容--></div>
<p class="content1">...</p>
<p class="content2">...</p>
</body>
"""
soup = BeautifulSoup(html_doc, "lxml")
正式讲解搜索文档之前,我们有必要了解下 Beautiful Soup 的过滤器,这些过滤器在整个搜索的 API 中都有所体现,他们可以被用在 TAG 的 name 中,属性中,字符串中或他们的混合中。听起来有点绕是么,看几个例子就懂了。
1、根据 TAG 的 name 来查找标签,下面的例子会查找文档中的所有 b 标签。同时要注意统一传入 Unicode 编码以避免 Beautiful Soup 解析编码出错。
# demo 1
tags = soup.find_all('b')
print(tags)
#输出结果
[<b>首页</b>]
2、如果传入正则表达式作为参数,那么 Beautiful Soup 会通过正则表达式的 match() 来匹配内容。
# demo 2
import re
for tag in soup.find_all(re.compile("^b")):
print(tag.name)
#输出结果
body
b
3、如果传入列表参数,那么 Beautiful Soup 会将与列表中任意一个元素匹配的内容返回。
# demo 3
for tag in soup.find_all(['a', 'b']):
print(tag)
#输出结果
<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=', ')
#输出结果
html, head, title, body, p, b, p, a, a, a, div, p, p,
5、方法。我们可以定义一个方法,该方法只接受一个参数,若该方法返回 True 则表示当前元素匹配并且被找到,返回 False 意味着没找到。下面的例子展示了查找所有同时包含 class 属性和 id 属性的节点。
# 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)
#输出结果
<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>
大部分情况字符串过滤器就可以满足我们的需求,外加这个神奇的方法过滤器,我们就可以实现各种自定义需求了。
该函数搜索当前节点下的所有子节点,其签名如下find_all( name , attrs , recursive , text , **kwargs )。我们可以传入指定 TAG 的 name 来查找节点,上面已经举过例子了,这里不再赘述。我们来看几个其他的用法。
1、如果我们转入 find_all() 函数不是搜索内置的参数名,那么搜索是就会将该参数对应到属性上去。下文的例子表示查找 id 为 google 的节点。
搜索指定名字的属性时可以使用的参数值包括:字符串,正则表达式,列表,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'])
#输出结果
https://www.google.com
https://www.google.com
https://www.baidu.com
https://cn.bing.com
2、按照 CSS 类名搜索,但是镖师 CSS 的关键字 class 在 Python 中是内置关键字,从 Beautiful Soup 4.1.1 版本开始,可以通过 class_ 参数搜索有指定 CSS 类名的 TAG:
class_ 参数同样接受不同类型的过滤器:字符串,正则表达式,方法,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'])
#输出结果
https://www.google.com
https://www.baidu.com
https://cn.bing.com
google
baidu
bing
同时,因为 CSS 可以有多个值,所以我们可以分别搜索 CSS 中的每个值。
# demo 8
css_soup = BeautifulSoup('<p class="body strikeout"></p>', 'lxml')
tags = css_soup.find_all("p", class_="strikeout")
print(tags)
#输出结果
[<p class="body strikeout"></p>]
3、不仅可以按照标签和 CSS 来搜索整个文档,还可以使用 text 再按照内容来搜索。同时 text 还可以配合其他属性一起来完成搜索任务。
# 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)
#输出结果
google : ['Google']
baidu & bing : ['Baidu', 'Bing']
a[text=google] : [<a class="website" href="https://www.google.com" id="google">Google</a>]
4、限制返回数量
有时候文档树过于庞大,我们不想查查找整棵树,只想查找指定数量的节点,或者只想查找子节点,而不想查找孙子节点,指定 limit 或者 recursive 参数即可。
# demo 10
tag = soup.find_all("a", limit=1)
print(tag)
tags = soup.find_all("p", recursive=False)
print(tags)
#输出结果
[<a class="website" href="https://www.google.com" id="google">Google</a>]
[]
因为该对象的儿子节点没有 p 标签,所以返回的是空列表。
该函数只会返回一个结果,与 find_all(some_args, limit=1) 是等价的,唯一的区别就是该函数直接返回结果,而 find_all() 函数返回包含一个结果的列表。另外 find_all() 方法没有找到目标是返回空列表, find() 方法找不到目标时,返回 None。除此之外使用上没有其他差别。
除了 find_all() 和 find() 外,Beautiful Soup 中还有 10 个用于搜索的 API,其中中五个用的是与 find_all() 相同的搜索参数,另外 5 个与 find() 方法的搜索参数类似,区别仅是它们搜索文档的范围不同。
find_parents() 和 find_parent() 用来搜索当前节点的父节点。
find_next_siblings() 和 find_next_sibling() 对在当前节点后面解析的所有兄弟节点进行迭代。
find_previous_siblings() 和 find_previous_sibling() 对在当前节点前面解析的所有兄弟节点进行迭代。
find_all_next() 和 find_next() 对当前节点之后的 TAG 和字符串进行迭代。
find_all_previous() 和 find_previous() 对当前节点之前的 TAG 和字符串进行迭代。
以上五组函数的区别仅仅是前者返回一个所有符合搜索条件的节点列表,而后者只返回第一个符合搜索条件的节点。
因为这 10 个 API 的使用和 find_all() 与 find() 大同小异,所有i这里不再举例,读者可以自己探索。
在 Tag 或 BeautifulSoup 对象的 .select() 方法中传入字符串参数即可使用 CSS 选择器的语法找到 TAG。
1、通过某个标签逐层查找。
# demo 11
tags = soup.select("body a")
for tag in tags:
print(tag['href'])
#输出结果
https://www.google.com
https://www.baidu.com
https://cn.bing.com
2、查找某个标签下的直接子标签
# demo 12
tags = soup.select("p > a")
print(tags)
tags = soup.select("p > #google")
print(tags)
#输出结果
[<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)
#输出结果
Google
Baidu
Bing
4、通过标签的 id 属性查找
# demo 14
tags = soup.select("#google")
print(tags)
#输出结果
[<a class="website" href="https://www.google.com" id="google">Google</a>]
5、通过属性的值来查找
击查看效果动图
知识点:移动端适配,跨域jsonp处理,
原生javascript封装jsonp,ajax与跨域原理讲解,
图片等比缩放算法, 瀑布流实现原理讲解,
百度图片内部请求入口.JavaScript编程原理与事务处理思考
PS:javascript不是做几个特效就可以说学会了的,做简单特效其实只是javascript的一个最简单的运用,群内很多伙伴都说现在找工作找不到,什么都学了,连面试机会都没有,这不是所谓的前端需求满了,而是很多伙伴学的并不扎实,很多基础的东西都没有学好,作为很多框架和插件的基础,原生javascript一定是非常重要的,这次分享,就是做了一个对原生javascript稍微深层次的利用,有什么不懂得或者不足的,欢迎指正!附上完整源码/视频以及注释!
如果想要更多的企业求职加分项目,案例,可以来一下我的前端群216634437,每天都会精挑细选一个特效,项目出来详细讲解,分享!
HTML/javascript移动端百度图片搜索源码:
需要文档版源码来我的前端群216634437,已上传到群文件
移动端javascript百度图片搜索视频:原生JavaScript实现移动端百度图片搜索
头条号里有许多web前端学习视频,企业常用特效/案例/项目,敬请关注!
下期群内分享:
想思路思路思路!!!!
*请认真填写需求信息,我们会在24小时内与您取得联系。