xml地图|网站地图|网站标签 [设为首页] [加入收藏]
python爬虫之Beautifulsoup学习笔记,一等对象
分类:编程

正文首要内容

一级对象

日常函数 & 高阶函数

可调用对象 & 自定义可调用类型

  函数内省

  函数注释

 

python高级——目录

文中代码均位居github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

 

  用一了段时间NSQ照旧很平稳的。除了安居,还可能有三个极度值的说的便是布局特别轻巧。总想写点什么推荐给大家使用nsq来做一些东西。可是正是因为他太轻松易用,文书档案也比较轻易易懂。一向不晓得要写吗!!!!!

相关内容:

什么是beautifulsoup

bs4的使用

  • 导入模块
  • 选用使用解析器
  • 行使标签字查找
  • 使用findfind_all查找
  • 使用select查找

 

首发时间:2018-03-02 00:10

 


风姿罗曼蒂克品对象

'''
    在python中,"一等对象"指的是满足下述条件的程序实体:
    (1)在运行时创建
    (2)能赋值给变量或数据结构中的元素
    (3)能作为参数传给函数
    (4)能作为函数的返回结果

    整数、字符串和字典都是一等对象。在面向对象编程中,函数也是对象,并满足以上条件,所以函数也是一等对象,称为"一等函数"
'''


if __name__ == "__main__":
    # 函数的一等性质
    def foo(n):
        '''returns  n!'''
        return 1 if n < 2 else n * foo(n-1)

    print(foo(5))    # 120

    my_foo = foo
    print(my_foo)    # <function foo at 0x1010e3f28> 能赋值给变量
    print(list(map(my_foo, range(6))))   # [1, 1, 2, 6, 24, 120]   能赋值给函数

    def foo2():
        return foo

    my_foo2 = foo2()
    print(my_foo2(5))     # 120 可作为函数的返回结果

 

  nsq官网: 

什么是beautifulsoup:

  • 是三个得以从HTML或XML文件中领取数额的Python库.它能够通过你赏识的转变器完成惯用的文书档案导航,查找,改正文书档案的格局.(官方)
  • beautifulsoup是贰个剖判器,能够一定的深入分析出内容,省去了大家编辑正则表明式的分神。

 

 

Beautiful Soup 3 目前曾经终止开辟,大家推荐在近期的项目中应用Beautiful Soup 4

beautifulsoup的版本:最新版是bs4


平凡函数 & 高阶函数

'''
    我们一般将函数分为"普通函数"和"高阶函数",接受函数为参数的函数为高阶函数,其余为普通函数

    普通函数大家再熟悉不过,本文不讲,主要讲一下map、filter、reduce三个高阶函数
'''


if __name__ == "__main__":
    # map第一个参数接受一个函数,并将这个函数作用于后面可迭代对象的每一个元素中
    l = map(lambda x : x ** 2, range(11))   # 返回的是生成器类型
    print(list(l))     # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    w = map(str.upper, 'asfafasfasfaf')
    print(list(w))     # ['A', 'S', 'F', 'A', 'F', 'A', 'S', 'F', 'A', 'S', 'F', 'A', 'F']

    # filter第一个参数也接受函数,并返回所有满足该函数的元素
    l = filter(lambda n: n % 2, range(10))   # 返回n % 2为真的数,就是奇数
    l2 = filter(lambda n: n % 2 ==0, range(10))  # 返回偶数
    print(list(l))                           # [1, 3, 5, 7, 9]
    print(list(l2))                          # [0, 2, 4, 6, 8]

    # reduce 从python3开始,reduce放在functools中
    # reduce将某个操作连续应用到序列元素上,即其会将前一步的结果继续应用到下一个元素上
    from functools import reduce
    s = reduce(lambda x,y: x + y, range(101))
    print(s)       # 5050 对1到100求和

 

  图片 1

bs4的使用:

 可调用对象 & 自定义可调用类型

'''
    我们在使用函数或者实例化对象的时候会用到括号(即()),这个括号实际上是调用运算符,python里面有7中可调用对象:

    1、用户定义的函数
        def和lambda创建
    2、内置函数
        使用C语言实现的函数,如len或time.strftime
    3、内置方法
        使用C语言实现的方法,如dict.get
    4、方法
        在类的定义体中定义的函数
    5、类
        调用类时其实首先运行的是__new__方法,然后运行__init__方法。这里很有意思,自定义类中其实没有重写__new__方法,
        而是调用的超类的__new__方法,如果查看源代码的实现逻辑,相信你会有新的发现,这里不做讨论。
    6、类的实例
        如果类定义了__call__方法,那么它的实例可以作为函数调用
    7、生长器函数
        使用yield关键字的函数或方法。
'''


if __name__ == "__main__":
    # 创建一个自定义可调用类
    class Foo():
        def __init__(self):
            self.name = "Foo"
        def __call__(self, *args, **kwargs):
            print("调用__call__")

    Foo()()     # 输出:调用__call__

    # 以上使用 Foo()() 这种写法看上去很有意思。首先,Foo()会创建一个Foo实例,调用__init__构造方法,; 然后使用实例(),此时
    # 调用__call__方法

 

  为了容灾要求对nsqd多机器部属,有了Docker后,迅速扩依旧很实惠的。

1.导入模块:

from bs4 import beautifulsoup

函数内省

'''
    函数内省我们通过例子来看
'''


if __name__ == "__main__":
    # 先创建一个函数
    def foo(n):
        ''':returns n!'''
        return 1 if n<2 else n*foo(n-1)

    print(foo.__doc__)   # :returns n!   __doc__里面存储了注释内容

    # 看看这个函数中有多少属性
    print(dir(foo))
    '''
        ['__annotations__', '__call__', '__class__', '__closure__', '__code__', 
        '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
        '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', 
        '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', 
        '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', 
        '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    '''

    # 下表对一些属性做了说明
名称 类型 说明
__annotations__ dict 参数和返回值的注解
__call__ method-wrapper 实现()运算符
__closure__ tuple 函数闭包
__code__ code 编译成字节码的函数元数据和函数定义体
__defaults__ tuple 形式参数的默认值
__get__ method-wrapper 实现只读描述符协议
__globals__ dict 函数所在模块中的全局变量
__kwdefaults__ dict 仅限关键字形式参数的默认值
__name__ str 函数名称
__qualname__ str 函数的限定名称

 

  布置完后自个儿会用go和c#写一些代码方便大家学习。

2.选项拆解剖析器解析钦定内容:

soup=beautifulsoup(剖析内容,深入解析器)

常用深入分析器:html.parser,lxml,xml,html5lib

有的时候候要求安装安装拆解剖析器:比方pip3 install lxml

BeautifulSoup默许扶助Python的行业内部HTML深入剖析库,可是它也协理部分第三方的解析库:

图片 2

深入分析器之间的差距 #这里摘自官方文书档案

Beautiful Soup为不一样的拆解分析器提供了相符的接口,但拆解深入分析器自己时有区别的.同风度翩翩篇文书档案被分裂的解析器解析后只怕会变卦分化结构的树型文书档案.不相同最大的是HTML解析器和XML解析器,看上边片段被分析成HTML结构:

BeautifulSoup("<a><b /></a>")
# <html><head></head><body><a><b></b></a></body></html>

因为空标签<b />不相符HTML规范,所以拆解深入分析器把它深入分析成<b></b>

相像的文书档案使用XML剖析如下(深入分析XML须求安装lxml库).注意,空标签<b />依然被保存,况兼文书档案前增加了XML头,并非被含有在<html>标签内:

BeautifulSoup("<a><b /></a>", "xml")
# <?xml version="1.0" encoding="utf-8"?>
# <a><b/></a>

HTML剖判器之间也可能有分别,假使被深入分析的HTML文书档案是明媒正礼格式,那么深入分析器之间从未别的异样,只是分析速度差异,结果都会重回准确的文档树.

然而后生可畏旦被拆解解析文书档案不是规范格式,那么差别的解析器再次来到结果或许不一样.上面例子中,使用lxml深入分析错误格式的文书档案,结果</p>标签被直接忽视掉了:

BeautifulSoup("<a></p>", "lxml")
# <html><body><a></a></body></html>

选取html5lib库剖判相通文档会获得分歧的结果:

BeautifulSoup("<a></p>", "html5lib")
# <html><head></head><body><a><p></p></a></body></html>

html5lib库没有忽略掉</p>标签,而是自行补全了标签,还给文档树加多了<head>标签.

接受pyhton内置库拆解深入分析结果如下:

BeautifulSoup("<a></p>", "html.parser")
# <a></a>

与lxml [7] 库相似的,Python内置库忽视掉了</p>标签,与html5lib库差异的是规范库未有品味创造符合标准的文书档案格式或将文书档案片段包蕴在<body>标签内,与lxml差别的是规范库以至连<html>标签都不曾品味去增加.

因为文书档案片段“<a></p>”是指鹿为马格式,所以上述分析方法都能算作”准确”,html5lib库使用的是HTML5的某个职业,所以最相近”正确”.可是全数剖判器的协会都能够被感觉是”符合规律”的.

不等的深入分析器大概影响代码执行结果,若是在散发给别人的代码中使用了 BeautifulSoup ,那么最棒申明使用了哪个种类分析器,以裁减不供给的麻烦.

函数注释

'''
    函数注解很简单,用下面例子简单讲解即可明了
'''


if __name__ == "__main__":
    def foo(num: int, step: 'int 间隔(大于0小于num)'=1) -> int:
        ''':returns 求num的阶乘,可以设置步长'''     # 这里的注释存储在__doc__中
        return num if num <= step else num * foo(num-step,step)

    print(foo(5))  # 120   (5*4*3*2*1)
    print(foo(5, 2))  # 15 (5*3)

    # 函数声明中的各个参数可以在冒号(:)之后增加注释,该注释可以直接写参数类型,也可以写字符串
    # -> 符号后面是对函数返回值进行注解

    # 这些注释内容存储在属性 __annotations__中
    print(foo.__annotations__)  # {'step': 'int 间隔(大于0小于num)', 'num': <class 'int'>, 'return': <class 'int'>}

    # 这样注释后,在使用pycharm时会出现自动提示

 

 

 

 

3.操作【约定soup是beautifulsoup(深入分析内容,深入解析器)再次来到的分析对象】:

python高档类别作品目录

python高级——目录

 

  筹算干活:

使用标签名查找

利用标具名来获取结点:

  • soup.标签名

行使标签名来获取结点标具名【这些首固然name,首要用来非标准化签名式筛选时,获取结果的价具名】:

  • soup.标签.name

利用标具名来获取结点属性:

  • soup.标签.attrs【获取全部天性】
  • soup.标签.attrs[属性名]【获取钦点属性】
  • soup.标签[属性名]【获取钦点属性】
  • soup.标签.get(属性名)

运用标签字来获取结点的文件内容:

  • soup.标签.text
  • soup.标签.string
  • soup.标签.get_text()

填补1:上边包车型地铁筛选情势得以接受嵌套:

print(soup.p.a)#p标签下的a标签

增加补充2:以上的name,text,string,attrs等办法都得以运用在当结果是叁个bs4.element.Tag对象的时候:图片 3

from bs4 import BeautifulSoup

html = """
<html >
<head>
    <meta charset="UTF-8">
    <title>this is a title</title>
</head>
<body>
<p class="news">123</p>
<p class="contents" id="i1">456</p>
<a href="http://www.baidu.com">advertisements</a>
</body>
</html>
"""

soup = BeautifulSoup(html,'lxml')

print("获取结点".center(50,'-'))
print(soup.head)#获取head标签
print(soup.p)#返回第一个p标签
#获取结点名
print("获取结点名".center(50,'-'))
print(soup.head.name)
print(soup.find(id='i1').name)
#获取文本内容
print("获取文本内容".center(50,'-'))
print(soup.title.string)#返回title的内容
print(soup.title.text)#返回title的内容
print(soup.title.get_text())
#获取属性
print("-----获取属性-----")
print(soup.p.attrs)#以字典形式返回标签的内容
print(soup.p.attrs['class'])#以列表形式返回标签的值
print(soup.p['class'])#以列表形式返回标签的值
print(soup.p.get('class'))


#############
t=soup.title
print(type(t))#<class 'bs4.element.Tag'>
print(t.name)#title
print(t.text)

#嵌套选择:
print(soup.head.title.string)

获取子结点【直接获得也会获得到’n’,会认为’n’也是二个标签】:

  • soup.标签.contents【重返值是多个列表】
  • soup.标签.children【再次来到值是三个可迭代对象,获取实际子结点必要迭代】
  • 图片 4

得到子孙结点:

  • soup.标签.descendants【再次回到值也是八个可迭代对象,实际子结点需求迭代】

获得父结点:

  • soup.标签.parent

得到祖先结点[父结点,祖父结点,曾祖父结点…]:

  • soup.标签.parents【】

获得兄弟结点:

  • soup.next_sibling【获取前面包车型客车三个兄弟结点】
  • soup.next_siblings【获取前面全部的男士结点】【重临值是三个可迭代对象】
  • soup.previous_sibling【获取前一小朋友结点】
  • soup.previous_siblings【获取前边全数的男子儿结点】【重临值是叁个可迭代对象】

 

补给3:与增加补充2同等,上边包车型客车函数都得以动用在当结果是八个bs4.element.Tag对象的时候。

from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
    <a >78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com">advertisements</a>
aspan
</body>
</html>
"""
soup = BeautifulSoup(html, 'lxml')

#获取子结点
print("获取子结点".center(50,'-'))
print(soup.p.contents)
print("n")
c=soup.p.children#返回的是一个可迭代对象
for i,child in enumerate(c):
    print(i,child)

print("获取子孙结点".center(50,'-'))
print(soup.p.descendants)
c2=soup.p.descendants
for i,child in enumerate(c2):
    print(i,child)

print("获取父结点".center(50,'-'))
c3=soup.title.parent
print(c3)

print("获取父,祖先结点".center(50,'-'))
c4=soup.title.parents
print(c4)
for i,child in enumerate(c4):
    print(i,child)

print("获取兄弟结点".center(50,'-'))
print(soup.p.next_sibling)
print(soup.p.previous_sibling)
for i,child in enumerate(soup.p.next_siblings):
    print(i,child,end='t')
for i,child in enumerate(soup.p.previous_siblings):
    print(i,child,end='t')

 

  》两台服务器:192.168.0.49; 192.168.0.105.

使用findfind_all方式:

find( name , attrs , recursive , text , **kwargs )【根据参数来搜索相应的竹签,但只回去第一个契合条件的结果】

find_all( name , attrs , recursive , text , **kwargs ):【依据参数来找寻相应的价签,但只回去全体切合条件的结果】

筛选规范参数介绍:

  • name:为标签字,依据标具名来筛选标签

  • attrs:为属性,,依照属性键值对来筛选标签,赋值格局可认为:属性名=值,attrs={属性名:值}【但由于class是python关键字,须要运用class_】图片 5

  • text:为文本内容,依照钦赐文本内容来筛选出标签,【单独使用text作为筛选规范,只会回到text,所以经常与任何规范合营使用】

  • recursive:钦定筛选是还是不是递归,当为False时,不会在子结点的后代结点中寻觅,只会查找子结点

获得到结点后的结果是叁个bs4.element.Tag对象,所以对于获得属性、文本内容、标具名等操作能够参照后面“使用标签筛选结果”时提到的艺术

from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
    <a id='i2'>78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com">advertisements</a>
aspan
</body>
</html>
"""
soup = BeautifulSoup(html, 'lxml')

print("---------------------")
print(soup.find_all('a'),end='nn')
print(soup.find_all('a')[0])
print(soup.find_all(attrs={'id':'i1'}),end='nn')
print(soup.find_all(class_='news'),end='nn')
print(soup.find_all('a',text='123456'))#
print(soup.find_all(id='i2',recursive=False),end='nn')#
a=soup.find_all('a')
print(a[0].name)
print(a[0].text)
print(a[0].attrs)

  》须要在两台机器上安装好Docker

接收select筛选【select使用CSS选用法则】:

  • soup.select(‘标签字’),代表基于标签来筛选出钦定标签
  • CSS中#xxx代表筛选id,soup.select(‘#xxx’)代表基于id筛选出钦点标签,重回值是一个列表
  • CSS中.###意味着筛选class,soup.select('.xxx')代表基于class筛选出内定标签,重回值是二个列表
  • 嵌套select: soup.select(“#xxx .xxxx”),如(“#id2 .news”)便是id=”id2”标签下class=”news的价签,重返值是贰个列表
  • 得到到结点后的结果是多少个bs4.element.Tag对象,所以对于获得属性、文本内容、标签字等操作能够参照前边“使用标签筛选结果”时提到的秘籍

    from bs4 import BeautifulSoup html = """

    <meta charset="UTF-8">
    <title>Title</title>
    

    123456

    <a id='i2'>78910</a>
    

    advertisements aspan """ soup = BeautifulSoup(html, 'lxml') sp1=soup.select('span')#重临结果是一个列表,列表的成分是bs4成分标签对象

    print(soup.select("#i2"),end='nn') print(soup.select(".news"),end='nn') print(soup.select(".news #i2"),end='nn')

    print(type(sp1),type(sp1[0])) print(sp1[0].name)#列表里面包车型大巴元素才是bs4成分标签对象 print(sp1[0].attrs) print(sp1[0]['class'])

 

 

补充4:

对此代码不齐全的事态下,能够运用soup.prettify()来机关补全,日常景况下建议选用,防止止代码不齐。

from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
    <a id='i2'>78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com">advertisements</a>
aspan

</html>
"""
soup = BeautifulSoup(html, 'lxml')
c=soup.prettify()#上述html字符串中末尾缺少 和 </body>
print(c)

 

 

万生机勃勃想要获得更详尽的介绍,能够参谋官方文书档案,令人喜悦的是,有了比较轻巧的汉语版:


  》两台机器上镜头像的拉取 

docker pull nsqio/nsq

  大家在105上运营lookup, nsqd和客商端都要求连接那一个lookup。  

docker run --name lookupd -p 4160:4160 -p 4161:4161 nsqio/nsq /nsqlookupd

图片 6

  

  在105和49上运营nsqd, lookup之处要写105

docker run --name nsqd -p 4150:4150 -p 4151:4151     nsqio/nsq /nsqd     --broadcast-address=192.168.0.105     --lookupd-tcp-address=192.168.0.105:4160

docker run --name nsqd -p 4150:4150 -p 4151:4151     nsqio/nsq /nsqd     --broadcast-address=192.168.0.49     --lookupd-tcp-address=192.168.0.105:4160

本文由澳门新葡亰手机版发布于编程,转载请注明出处:python爬虫之Beautifulsoup学习笔记,一等对象

上一篇:递归算法的理解与应用,不同系统下的可执行文 下一篇:没有了
猜你喜欢
热门排行
精彩图文