什么是Beautiful Soup库

  • Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能
  • 它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序
  • Beautiful Soup就是python的一个库,最主要的功能是从网页获取数据
  • BeautifulSoup4==4.7.1第四版本,简称bs4

学习Beautiful Soup库的目的

增加一种获取数据的方法

安装Beautiful Soup库

cmd输入以下命令:

pip install beautifulsoup4

结果报错了,解决方案:在d:\python\python37\lib\site-packages目录下删除~ip开头的目录文件夹

重新执行命令

Beautiful Soup支持的解析器

解析器 使用方法 优势 劣势
python标准库 BeautifulSoup(markup,"html.parser") python的内置标准库,执行速度适中、文档容错能力强 python 2.7.3及Python 3.2.2之前的版本文档容错能力差
lxml HTML解析器 BeautifulSoup(markup,"lxml") 速度快、文档容错能力强 需要安装C语言库
lxml XML解析器 BeautifulSoup(markup,"xml") 速度快,唯一支持XML的解析器 需要安装C语言库
html5lib BeautifulSoup(markup,"html5lib") 最好的容错性、以浏览器的方式解析文档、生成HTML5的格式的文档 速度慢、不依赖外部扩展

实际工作中前两个用的最多,前两个中重点掌握第二个;后面的笔记以lxml为主

安装lxml解析器

pip install lxml

我之前已经安装过了,所以没有安装过程截图。

 

解析节点及属性值

示例

 1 #安装的是beautifulsoup4,但是导包的时候,是通过bs4来导入的,并且导入的是大写的BeautifulSoup
2 from bs4 import BeautifulSoup
3
4 html = """
5 <html><head><title>The Dormouse's story</title></head>
6 <body>
7 <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
8 <p class="story">Once upon a time there were three little sisters; and their names were
9 <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
10 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
11 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
12 and they lived at the bottom of a well.</p>
13 <p class="story">...</p>
14 """
15 #lxml提前安装好,pip install lxml,第一个参数是html代码段,第二个参数是解析器
16 soup = BeautifulSoup(html,'lxml')
17 #查看经过bs4实例化,初始化的代码段
18 # print(soup.prettify())
19 #获取到的是数据结构,tag,tag有很多方法,如string
20 # print(type(soup.title))
21 #来查看文档中title的属性值
22 # print(soup.title.string)
23 # print(soup.head)
24 #当有多个节点的时候,我们当前的这种选择模式,只能匹配到第一个节点,其他节点会被忽略
25 # print(soup.p)
26 #获取节点的名称
27 # print(soup.title.name)
28 #attrs会返回标签的所有属性值,返回的是一个字典
29 # print(soup.p.attrs)
30 # print(soup.p.attrs['name'])
31 #返回的节点属性,可能是列表,也可能是字符串,需要进行实际的判断
32 # print(soup.p['name'])
33 # print(soup.p['class'])
方法 作用 示例结果
soup = BeautifulSoup(html,'lxml')
实例化对象,解析器用的是lxml
>> print(type(soup))
<class 'bs4.BeautifulSoup'>
soup.prettify()
初始化代码段,即将示例不规则代码,
进行初始化规范后输出
soup.title
获取到的是数据结构tag,tag有很多
方法,如string/text
>>> print(type(soup.title))
>>> print(dir(soup.title))
>>> print(soup.title.text)

soup.title.string
查看文档中title的属性值
>>>print(soup.title)
<title>The Dormouse's story</title> >>>print(soup.title.string)
The Dormouse's story
soup.p
当有多个节点的时候,我们当前的这种
选择模式,只能匹配到第一个节点,其
他节点会被忽略
>>> print(soup.p)
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
soup.title.name
获取节点的名称
>>> print(soup.title.name)
title
soup.p.attrs
attrs会返回标签的所有属性值,返回的
是一个字典;当有多个节点的时候,只能
匹配到第一个节点,其他节点会被忽略
>>> print(soup.p.attrs)
{'class': ['title'], 'name': 'dromouse'}
>>> print(soup.p.attrs['name'])
dromouse
soup.p['name']
soup.p['class']
返回的节点属性,可能是列表,也可能是
字符串,需要进行实际的判断;当有多个
节点的时候,只能匹配到第一个节点,其
他节点会被忽略
>>> print(soup.p['name'])
dromouse >>> print(soup.p['class'])
['title']

BeautifulSoup解析节点,只能匹配第一个节点!!!

获取子节点和孙节点

示例-1:嵌套调用

 1 #嵌套调用
2
3 from bs4 import BeautifulSoup
4
5 html = """
6 <html><head><title>The Dormouse's story</title></head>
7 <body>
8 <p class="title" name="dromouse"><b>The Dormouse's story</b></p>
9 <p class="story">Once upon a time there were three little sisters; and their names were
10 <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
11 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
12 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
13 and they lived at the bottom of a well.</p>
14 <p class="story">...</p>
15 """
16
17 soup = BeautifulSoup(html,'lxml')
18 #嵌套调用,查找head节点下面的title节点
19 print(soup.head.title)
20
21 #两个都是bs4.element.Tag
22 print(type(soup.head))
23 print(type(soup.head.title))
24
25 #查找head节点下面的title节点的内容
26 print(soup.head.title.string)
方法 作用 示例结果
soup.head.title
嵌套调用,查找head节点下面的title节点

>>> print(soup.head.title)
<title>The Dormouse's story</title>

soup.head
soup.head.title

查看两个节点的类型,都是bs4.element.Tag

>>> print(type(soup.head))
>>> print(type(soup.head.title))
<class 'bs4.element.Tag'>
<class 'bs4.element.Tag'>

soup.head.title.string

查找head节点下面的title节点的内容

>>> print(soup.head.title.string)
The Dormouse's story

示例-2:子节点和子孙节点调用

 1 #子节点和子孙节点
2 from bs4 import BeautifulSoup
3
4 html = """
5 <html>
6 <head>
7 <title>The Dormouse's story</title>
8 </head>
9 <body>
10 <p class="story">
11 Once upon a time there were three little sisters; and their names were
12 <a href="http://example.com/elsie" class="sister" id="link1">
13 <span>Elsie</span>
14 </a>
15 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>
16 and
17 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>
18 and they lived at the bottom of a well.
19 </p>
20 <p class="story">...</p>
21 """
22
23 soup = BeautifulSoup(html,'lxml')
24
25 #获取p标签的子节点,注意是子节点,返回的是一个列表
26 #列表中的元素是p节点的直接子节点
27 #返回结果没有单独的吧a标签中的span标签选出来
28 #contents方法获取直接子节点的列表
29 print(soup.p.contents)
30 print(soup.p.contents[0])
31 print(len(soup.p.contents))
32
33 #contents和children返回的结果是一样的,都是直接子节点
34 #只不过children方法返回的是一个迭代器,需要使用for循环来进行遍历
35 print(soup.p.children)
36 for i,j in enumerate(soup.p.children):
37 print(i,j)
38 print("==============================")
39
40 #获取子节点和孙节点
41 #会把中间的孙节点也单独的取出来
42 print(soup.p.descendants)
43 for i,j in enumerate(soup.p.descendants):
44 print(i,j)
方法 作用 示例结果
soup.p.contents
获取p标签的子节点,注意是子节点,返回的是一个列表;
列表中的元素是p节点的直接子节点;
返回结果没有单独的吧a标签中的span标签选出来;
contents方法获取直接子节点,返回数据类型是列表;

>>> print(soup.p.contents)

>>> print(soup.p.contents[0])
            Once upon a time there were three little sisters; and their names were
>>> print(len(soup.p.contents))
7

soup.p.children

contents和children返回的结果是一样的,都是直
接子节点;
只不过children方法返回的是一个迭代器,需要使用
for循环来进行遍历

>>> print(soup.p.children)
<list_iterator object at 0x000001F6C4743C88>
>>> for i,j in enumerate(soup.p.children):
print(i,j)

soup.p.descendants

获取p标签子节点和孙节点;
会把中间的孙节点也单独的取出来;
返回的是一个迭代器;

>>> print(soup.p.descendants)
<generator object Tag.descendants at 0x00000214B2661648>
>>> for i,j in enumerate(soup.p.descendants):
  print(i,j)

这个里面直接子节点和子节点是有区别的,可能不太容易理解,简单讲解一下:

直接子节点:

  • contents;children
  • 所有儿子节点,至于你儿子节点里面有没有孙子节点,都跟你儿子节点算一个
  • 人家跟你说:明天来吃席,一家都来哈。第二天你们家都去了,不分大人小孩坐在了一桌

子节点

  • descendants
  • 所有儿子节点输出的同时,如果节点里面有孙子、重孙子...节点的依次输出
  • 人家跟你说:明天来吃席,一家都来哈。第二天你们家都去了,先看你家人都到了没有,先做一桌子,输出一下;以家为单位输出结束后,再依次输出你孙子一大家、然后重孙子一大家

获取父节点、祖先节点、兄弟节点

示例-1:获取父节点、祖先节点

 1 #获取父节点和获取祖先节点
2
3 from bs4 import BeautifulSoup
4
5 html = """
6 <html>
7 <head>
8 <title>The Dormouse's story</title>
9 </head>
10 <body>
11 <p class="story">
12 Once upon a time there were three little sisters; and their names were
13 <a href="http://example.com/elsie" class="sister" id="link1">
14 <span>Elsie</span>
15 </a>
16 </p>
17 <p class="story">...</p>
18 """
19
20 soup = BeautifulSoup(html,'lxml')
21 #获取a节点的父节点
22 print(soup.a.parent)
23
24 #获取所有的祖先节点,返回的是迭代器
25 print(soup.a.parents)
26 for i,j in enumerate(soup.a.parents):
27 print(i,j)
方法 作用 示例结果
soup.a.parent
获取a节点的父节点;

>>> print(soup.a.parent)

soup.a.parents

依次往上找,获取所有的祖先节点,
返回的是迭代器

>>> print(soup.a.parents)
<generator object PageElement.parents at 0x000001DE4A3F3648>
>>> for i,j in enumerate(soup.a.parents):
  print(i,j)

示例-2:获取兄弟节点

 1 from bs4 import BeautifulSoup
2
3 html = """
4 <html>
5 <body>
6 <p class="story">
7 Once upon a time there were three little sisters; and their names were
8 <a href="http://example.com/elsie" class="sister" id="link1">
9 <span>Elsie</span>
10 </a>
11 Hello
12 <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a>
13 and
14 <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>
15 and they lived at the bottom of a well.
16 </p>
17 """
18
19 soup = BeautifulSoup(html,'lxml')
20 #获取a标签的下一个兄弟节点
21 # print(soup.a.next_sibling)
22
23 #获取上一个兄弟节点
24 # print(soup.a.previous_sibling)
25
26 #获取当前节点后面的所有兄弟节点
27 # print(soup.a.next_siblings)
28 # for i,j in enumerate(soup.a.next_siblings):
29 # print(i,j)
30
31 #获取当前节点前面所有的兄弟节点
32 print(soup.a.previous_siblings)
33 for i,j in enumerate(soup.a.previous_siblings):
34 print(i,j)
方法 作用 示例结果
soup.a.next_sibling
获取a标签的下一个兄弟节点

>>> print(soup.a.next_sibling)

Hello

soup.a.previous_sibling

获取上一个兄弟节点

>>> print(soup.a.previous_sibling)
Once upon a time there were three little sisters; and their names were
soup.a.next_siblings

获取当前节点后面的所有兄弟节点

>>> print(soup.a.next_siblings)
<generator object PageElement.next_siblings at 0x0000018C60652648>

>>> for i,j in enumerate(soup.a.next_siblings):
print(i,j)

soup.a.previous_siblings

获取当前节点前面所有的兄弟节点

>>> print(soup.a.previous_siblings)
<generator object PageElement.previous_siblings at 0x000001246F202648>

>>> for i,j in enumerate(soup.a.previous_siblings):
print(i,j)

方法选择器

find和find_all方法

  • find_parents 和 find_parent:前者返回所有祖先节点,后者返回直接父节点。
  • find_next_siblings 和 find_next_sibling:前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点。
  • find_previous_siblings 和 find_previous_sibling:前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点。
  • find_all_next 和 find_next:前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
  • find_all_previous 和 find_previous:前者返回节点前所有符合条件的节点,后者返回第一个符合条件的节点。
方法 表达式 示例
soup.find_all()
find_all:返回的是列表
find:返回的是单个元素,即第一个符合条件的 **kwargs说明:
name="data"
获取到当前文本中data标签的数据 attrs={"key":"value"}
attrs,传入的是属性参数和值,类型是字典,attrs={"id":"list-1"} id="data"
查找id属性值为data的数据 class_="data"
查找class属性值为data的数据,用class的时候,后面加上一个下划线 text=re.compile("正则表达式")
通过text参数来获取文本的值,可以传递正则表达式,返回是一个列表
#attrs,传入的是属性参数,类型是字典,attrs={"id":"list-1"}
print(soup.find_all(attrs={"id":"list-1"}))
print(soup.find_all(attrs={"name":"elements"}))
#也可以直接传入ID这个参数
print(soup.find_all(id="list-1"))
#class在Python中是一个关键字,find_all方法里面要用class的时候,后面加上一个下划线
print(soup.find_all(class_="list"))
#可以通过text参数来获取文本的值,可以传递正则表达式,返回是一个列表
print(soup.find_all(text=re.compile("Foo\d")))
soup.find()

#find方法,返回的是一个单个的元素,第一个匹配的元素,而find_all返回的是所有值的列表
print(soup.find(name="ul"))
find_parents 和 find_parent:前者返回所有祖先节点,后者返回直接父节点
find_next_siblings 和 find_next_sibling:前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点
find_previous_siblings 和 find_previous_sibling:前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点
find_all_next 和 find_next:前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点
 find_all_previous 和 find_previous:前者返回节点前所有符合条件的节点,后者返回第一个符合条件的节点

示例-1:find_all通过节点名进行查询

 1 #方法选择器,find_all,通过节点名来进行查询的
2
3 from bs4 import BeautifulSoup
4
5 html='''
6 <div class="panel">
7 <div class="panel-heading">
8 <h4>Hello</h4>
9 </div>
10 <div class="panel-body">
11 <ul class="list" id="list-1">
12 <li class="element">Foo</li>
13 <li class="element">Bar</li>
14 <li class="element">Jay</li>
15 </ul>
16 <ul class="list list-small" id="list-2">
17 <li class="element">Foo</li>
18 <li class="element">Bar</li>
19 </ul>
20 </div>
21 </div>
22 '''
23
24 soup = BeautifulSoup(html,'lxml')
25 #find_all,name=li,可以获取到当前文本中所有li标签的数据,返回的是一个列表
26 print(soup.find_all(name='li')) #[<li class="element">Foo</li>, <li class="element">Bar</li>, <li class="element">Jay</li>, <li class="element">Foo</li>, <li class="element">Bar</li>]
27 print(soup.find_all(name='li')[0]) #<li class="element">Foo</li>
28
29 #tag类型
30 print(type(soup.find_all(name='li')[0])) #<class 'bs4.element.Tag'>
31
32 #可以进行嵌套查询
33 for ul in soup.find_all(name="ul"):
34 for li in ul.find_all(name='li'):
35 #tag
36 print(li.string) #FooBar Jay Foo Bar

示例-2:find_all通属性进行查询

 1 #通过属性来进行查询
2 #通过text文本来获取匹配的文本
3
4 import re
5 from bs4 import BeautifulSoup
6
7 html='''
8 <div class="panel">
9 <div class="panel-heading">
10 <h4>Hello</h4>
11 </div>
12 <div class="panel-body">
13 <ul class="list" id="list-1" name="elements">
14 <li class="element">Foo</li>
15 <li class="element">Bar</li>
16 <li class="element">Jay</li>
17 </ul>
18 <ul class="list" id="list-1">
19 <li class="element">Foo2</li>
20 <li class="element">Bar2</li>
21 <li class="element">Jay2</li>
22 </ul>
23 <ul class="list list-small" id="list-2">
24 <li class="element">Foo</li>
25 <li class="element">Bar</li>
26 </ul>
27 </div>
28 </div>
29 '''
30
31 soup = BeautifulSoup(html,'lxml')
32 #attrs,传入的是属性参数,类型是字典,attrs={"id":"list-1"}
33 print(soup.find_all(attrs={"id":"list-1"}))
34 print(soup.find_all(attrs={"name":"elements"}))
35
36 #也可以直接传入ID这个参数
37 print(soup.find_all(id="list-1"))
38
39 #class在Python中是一个关键字,find_all方法里面要用class的时候,后面加上一个下划线
40 print(soup.find_all(class_="list"))
41
42 #可以通过text参数来获取文本的值,可以传递正则表达式,返回是一个列表
43 print(soup.find_all(text=re.compile("Foo\d")))
44
45 #find方法,返回的是一个单个的元素,第一个匹配的元素,而find_all返回的是所有值的列表
46 print(soup.find(name="ul"))

使用css选择器获取元素

  • 建议大家使用find find_all查询匹配单个结果或多个结果
  • css选择器非常的熟悉,那么就可以使用css选择器
#使用css选择器,只需要呢,调用select方法,传入css选择器即可

from bs4 import BeautifulSoup

html='''
<div class="panel">
<div class="panel-heading">
<h4>Hello</h4>
</div>
<div class="panel-body">
<ul class="list" id="list-1">
<li class="element">Foo</li>
<li class="element">Bar</li>
<li class="element">Jay</li>
</ul>
<ul class="list list-small" id="list-2">
<li class="element">Foo</li>
<li class="element">Bar</li>
</ul>
</div>
</div>
''' soup = BeautifulSoup(html,'lxml')
#需要调用select方法,传入css选择器,class用.来表示;通过空格继续书写子节点
# print(soup.select(".panel .panel-heading")) #获取ul标签下所有Li标签
# print(soup.select("ul li")) #获取id为list-2,class为element两个Li标签;id属性简写是#
# print(type(soup.select("#list-2 .element")[0])) #支持嵌套选择
#先获取到ul标签,tag类型,for 调用select方法在次传入css选择器
for ul in soup.select("ul"):
for li in ul.select("li"):
#调用tag类型里面的方法,string方法来获取文本内容
# print(li.string)
print(li['class']) #支持使用属性获取元素
# for ul in soup.select("ul"):
# print(ul['id']) #建议大家使用find find_all查询匹配单个结果或多个结果
#css选择器非常的熟悉,那么就可以使用css选择器

案例-BS4解析网站数据

 1 import requests
2 from bs4 import BeautifulSoup
3
4
5 def handle_detail_bs4(content):
6 """
7 解析目标页面返回数据的
8 :param content:response.text
9 :return:
10 """
11 # 数据的实例化,传入要解析的数据,和解析器,解析器使用的是lxml
12 soup = BeautifulSoup(content, "lxml")
13 # 获取所有的图书条目,使用find_all,查找div标签,通过class属性查找,class是一个关键字,class_
14 all_book_items = soup.find_all("div", class_="row col-padding")
15 # 打印未格式化的数据,可以看到html标签的
16 for item in all_book_items:
17 # print(item)
18 # 获取图书信息,先查找上层的div,发现里面包含着三个span,find_all来查找所有span
19 info = item.find("div", class_="col-md-7 flex-vertical description-font").find_all("span")
20 # 获取作者,出版社,价格信息
21 author_press_price = info[1].string.split("/")
22 if len(author_press_price) == 3:
23 print(
24 {
25 # 最终信息
26 "title": info[0].string,
27 "author": author_press_price[0],
28 "press": author_press_price[1],
29 "price": author_press_price[2],
30 "summary": info[2].string
31 }
32 )
33
34
35 def main():
36 header = {
37 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36"
38 }
39 for i in range(1, 5):
40 url = "http://yushu.talelin.com/book/search?q=python&page={}".format(i)
41 response = requests.get(url=url, headers=header)
42 handle_detail_bs4(response.text)
43
44
45 if __name__ == '__main__':
46 main()

爬虫(6) - 网页数据解析(2) | BeautifulSoup4在爬虫中的使用的更多相关文章

  1. 20170717_python_爬虫_网页数据解析_BeautifulSoup_数据保存_pymysql

    上午废了老大劲成功登陆后,下午看了下BeautifulSoup和pymysql,晚上记录一下 自己电脑装的sublime,字体颜色竟然拷贝不下来 - - 写的过程中遇到了很多问题: 1.模拟登陆部分 ...

  2. python爬虫的页面数据解析和提取/xpath/bs4/jsonpath/正则(1)

    一.数据类型及解析方式 一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值.内容一般分为两部分,非结构化的数据 和 结构化的数据. 非结构化数据:先有数据,再有结构, 结构化数 ...

  3. Python网络爬虫之三种数据解析方式

    1. 正则解析 正则例题 import re # string1 = """<div>静夜思 # 窗前明月光 # 疑是地上霜 # 举头望明月 # 低头思故乡 ...

  4. Python网络爬虫实战(二)数据解析

    上一篇说完了如何爬取一个网页,以及爬取中可能遇到的几个问题.那么接下来我们就需要对已经爬取下来的网页进行解析,从中提取出我们想要的数据. 根据爬取下来的数据,我们需要写不同的解析方式,最常见的一般都是 ...

  5. 05.Python网络爬虫之三种数据解析方式

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  6. python爬虫的页面数据解析和提取/xpath/bs4/jsonpath/正则(2)

    上半部分内容链接 : https://www.cnblogs.com/lowmanisbusy/p/9069330.html 四.json和jsonpath的使用 JSON(JavaScript Ob ...

  7. Python爬虫之三种数据解析方式

    一.引入 二.回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需 ...

  8. 05,Python网络爬虫之三种数据解析方式

    回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据 ...

  9. 《Python网络爬虫之三种数据解析方式》

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

随机推荐

  1. 我的树莓派 Raspberry Pi Zero 2W 折腾笔记,记录一些遇到的问题和解决办法

    0x00 前言说明 最近买了一块Raspberry Pi Zero 2W来玩,目的是想搭建一台远程运行的个人服务器,上面放个博客.点个灯啥的.于是就有了这篇文章. 树莓派官网地址:https://ww ...

  2. python学习-Day22

    目录 今日内容详细 hashlib加密模块 什么是加密 加密算法 加密的使用 基本使用 指定算法(md5) 将明文数据传递给算法对象 获取加密之后的密文数据 加密补充 加盐处理 动态加盐 加密应用场景 ...

  3. Redis实现并发阻塞锁方案

    由于用户同时访问线上的下订单接口,导致在扣减库存时出现了异常,这是一个很典型的并发问题,本篇文章为解决并发问题而生,采用的技术为Redis锁机制+多线程的阻塞唤醒方法. 在实现Redis锁机制之前,我 ...

  4. vant 使用field组件加载页面就触发input事件的坑,已解决

    使用vant的时候,遇到一个坑,加载组件就自动触发input事件,input事件里写了验证,导致已加载就验证错误 原因:v-model绑定的时候写的是null, filed组件接收的时候把他转换成空字 ...

  5. 痞子衡嵌入式:大话双核i.MXRT1170之在线联合调试双核工程的三种方法(IAR篇)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170下在线联合调试双核工程的方法(基于IAR). 前段时间痞子衡写过一篇<双核i.MXRT1170之单独在线调试从 ...

  6. 专门为小白准备的入门级mybatis-plus-generator代码自动生成器,提高开发效率。值得收藏

    引入依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-g ...

  7. 升级gradle后。需要修改jenkin 编译java版本从1.8 到11

    错误提示 * What went wrong: A problem occurred evaluating project ':App'. > Failed to apply plugin 'c ...

  8. 评估海外pop点网络质量,批量探测到整个国家运营商ip地址段时延

    1 查询当地供应商所有AS号和IP地址段,如下 可以手动复制也可以爬下来,此次测试地址不多,手动复制下来再做下格式话 61.99.128.0/17 61.99.0.0/16 61.98.96.0/20 ...

  9. django 备件管理系统

    views 1 class limit: 2 3 def limit(self,res,obj): 4 limit = int(res.GET.get('limit',1)) 5 pagelimit ...

  10. 709. To Lower Case - LeetCode

    Question 709. To Lower Case Sollution 题目大意:字符串大写转小写 思路: 直接调用Java API函数 字符串转char数组,遍历数组,判断如果大写就转小写 Ja ...