网络爬虫 使用BeautifulSoup包解析源代码

使用BeautifulSoup包解析源代码

  • 前导:BeautifulSoup自动将输入文档转换为Unicode便阿门,输出文档转换为utf-8编码
  • 解析方式(需要借助第三方库lxml) BeautifulSoup(markup,“lxml”) markup为获得的源代码,解析后产生一个类似于文档树的东西

1. 导入包

import requests
from bs4 import BeautifulSoup

2.获取网页

r = requests.get(url = "https://www.csdn.net/") #获取网页信息
print(r)
print(r.text)  #输出网页源代码

3.进行解析

  • 发现内容和r.text相同,但是类型已经变成BeautifulSoup的树状类型
soup = BeautifulSoup(r.text,'lxml')
print(soup)                   #发现内容类似r.text
print('*****************')
print(type(soup))             #发现类型不再是r.text的str,而是一种bs4的树状类型

4. 格式化输出(使用.prettify()方法)

  • 按照html的缩进方式输出结果
print(soup.prettify())

5. 提取html的标签 Tag

  • 使用以下方法只返回第一个标签内容
print(soup.title) #标题标签
print('***************************')
print(soup.head)  #头部信息
print('***************************')
print(soup.body)  #正文内容
print('***************************')
print(soup.a)     #链接标签

6. 对于标签的属性(用.name和.attrs)

  • 对于Tag,有两个属性:name(标签名称)和attrs(标签属性)
  • soup.name 较为特殊,它的name即为[document]
print(soup.title.name)
print(soup.div.name)
print(type(soup.div.name)) #以str形式返回
print(soup.name)  #较为特殊,树的顶层
print(soup.title.attrs)
print(soup.a.attrs)
print(soup.p.attrs)
print(type(soup.a.attrs)) #以字典形式返回
"""利用它的字典形式获取属性内容"""
print(soup.p.attrs['class'])

7. 提取html的标签元素文字(使用.string) NavigableString

  • 类型是一个NavigableString,可以遍历的字符串
    注意:.string只能用于单个标签,无法用于嵌套类型的标签
print(soup.title.string)
print(soup.a.string)
print(soup.p.string)
print(type(soup.title.string)) #
  • 使用.string和.text方法的区别

    1. string获取内容是可遍历字符串形式
    2. text获取内容只是文本str形式
    3. text可以显示嵌套标签内容,而string只能显示独立标签内容
    4. text显示没有元素的标签区块时空着
print(soup.title.string)
print(soup.title.text)
print(type(soup.title.string)) #string获取内容是可遍历字符串形式
print(type(soup.title.text))   #text获取内容只是文本str形式
print(soup.head.string)        #string只能显示独立标签内容
print(soup.head.text)          #text可以显示嵌套标签内容 #没有元素的标签区块空着

8. 直接子节点(使用.contents,.children)

所有子孙节点用(.descendants)

  • .contents返回列表,.children返回一个生成器
print(soup.head.contents)       #打印列表形式的内容
print(type(soup.head.contents)) #以一个列表返回
print('**********************')
print(type(soup.head.children)) #以一个生成器返回
for i in soup.head.children:    #打印生成器内容
    print(i)
  • 打印所有子孙节点用.descendants , 返回的也是一个生成器
print(type(soup.head.descendants))
for i in soup.head.descendants:
    print(i)

9. 父节点(只要一个父节点使用.parent,所有父节点用.parents)

  • .parent 返回的是一个节点结构
  • .parents返回的是一个生成器,每一个生成器结果都是一个节点结构
""".parent"""
print(type(soup.title.parent)) #只取一个父节点,是节点类型
print(soup.title.parent)    #直接打印上一节点所有内容
""".parents"""
print(type(soup.title.parents)) #取所有父节点,返回一个生成器,每一个生成器产生结果都是一个节点
for i in soup.title.parents:    #打印生成器内容
    print(i)
  • 打印所有父节点标签名
  • 打印到document说明上面已经没有父节点了
 """打印所有父节点标签名"""   
for i in soup.title.parents:
    print(i.name)     #打印到document说明上面已经没有父节点了

10.兄弟节点(.next_sibling和.previous_sibling 与 .next_siblings和.previous_siblings)

  • 理解为同一层次的节点
  • .next_sibling返回下一个兄弟节点, .previous_sibling返回上一个兄弟节点
  • .next_siblings返回下面所有兄弟节点组成的生成器, .previous_siblings返回上面所有兄弟节点组成的生成器
print(soup.title.next_sibling)
print(soup.title.next_sibling.previous_sibling) #返回到下面又返回上去到自己
print(type(soup.p.next_sibling))
print(type(soup.p.next_sibling))
for i in soup.title.next_siblings: #输出下面所有兄弟节点组成的生成器
    print(i)
print('*********************')
for i in soup.title.previous_siblings: #输出上面所有兄弟节点组成的生成器
    print(i)

11.前后节点(.next_element和.previous_element 与 .next_elements和.previous_elements

  • 与兄弟节点不同,并不是针对兄弟节点,而是在所有节点上不分层次的获取前后节点
  • .next_element和.previous_element返回一个节点
  • .next_elements和.previous_elements返回一个节点生成器
print(type(soup.div.next_element))
print(soup.div.next_element)
print(soup.div.previous_element)
for i in soup.div.next_elements:      #用生成器打印所有后节点
    print(i)
print('******************************')
for i in soup.div.previous_elements: #用生成器打印所有前节点
    print(i)

重点12. find_all()

  • 搜索当前tag所有子节点,并判断是否符合过滤的条件
  • find_all(name,attrs,recursive,string,**kwargs)
    其中’name’为标签名称,'attrs’为标签属性
print(soup.find_all('title'))      #按标签查找 返回所有'title'内容
print(soup.find_all('meta'))       #按标签查找 返回所有'meta'内容
print(type(soup.find_all('title'))) #返回的是一种bs4的列表形式
  • 使用name和attrs控制搜索范围
print(soup.find_all('img',"pre-img-lasy")) #按名称与属性内容查找,一般不用,而是选择keyword参数
  • 使用limit参数控制搜索量
print(soup.find_all('img',limit = 2)) #控制搜索量为2
  • keyword参数 比较重要
    1. 通过属性的关键字来查找 属性 = ‘内容’ 表示查找属性为’ '的标签内容
    2. 通过含有某一属性的来查找 属性 = True 表示查找所有包含这一属性的标签内容
    3. 通过正则re包来爬取特定内容
"""通过属性的关键字来查找"""
soup.find_all('meta',content="IE=Edge")  #其中content="IE=Edge"为属性内容关键字
"""查找所有含某一属性的来查找"""
soup.find_all('meta',content = True)    #查找所有含content属性的标签内容
  • 通过正则re来作为关键字加compile查找
import re #导入re正则包
print(soup.find_all('a',limit = 5))
print('*******************************************')
print(soup.find_all('a',href = re.compile("/nav/engin"))) #查找属性中含关键词"/nav/engin"的内容
for i in soup.find_all('a',href = re.compile('/nav/')):#输出生成器
    print(i.attrs['href'])                           #打印所有属性为href的内容
print('*******************************************')
for i in soup.find_all('a',href = re.compile('/nav/')):#输出生成器
    print(i.string)                           #打印所有查询到的元素(bs4内部一种结构)
print('*******************************************')
for i in soup.find_all('a',href = re.compile('/nav/')):#输出生成器
    print(i.text) 
  • find()函数,相比find_all(),只是找一个第一个

( 可以用find_all()中limit=1代替 )

print(soup.find('a'))
  • find()语句的嵌套
print(soup.find('div').find_all('li',limit = 2))    #使用find与find_all进行嵌套寻找

本文章所附带的Jupyter notebook文件中含有完整代码以及详细案例

你可能感兴趣的:(python,html,anaconda,http,javascript)