BeautifulSoup4和lxml
这两个库主要是解析html/xml文档,BeautifulSoup 用来解析 HTML 比较简单,API非常人性化,支持CSS选择器、
Python标准库中的HTML解析器,也支持 lxml 的 XML解析器。关于BeautifulSoup和lxml的实例介绍如下:
一、BeautifulSoup4库:
安装:pip install beautifulsoup4 如果不写4会默认安装beautifulsoup3
数据结构、种类:Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可
以归纳为4种: Tag NavigableString BeautifulSoup Comment 。
Tag: 即我们在写网页时所使用的标签(如<a>超链接标签)
NavigableString:简单的说就是一种可以遍历的字符串
搜索文档:
使用requests库获取网页源代码:
  1 import requests
  2 from bs4 import BeautifulSoup
  3 url = ‘https://www.baidu.com/s?wd=python‘
  4 headers = {
  5     ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) 
      Chrome/64.0.3282.140 Safari/537.36‘,}
  6 req = requests.session()
  7 response = req.get(url, headers=headers, verify=False)
  8 html_test = response.text
html_test就是获取的一个网页源代码,它没有爬取到JS的内容,所有可能和网页内容不完全一致!
要解析文档内容之前,先要用BeautifulSoup实例一个对象。如下,它的类型为<class ‘bs4.BeautifulSoup‘>
  1 soup = BeautifulSoup(html_test, ‘lxml‘)
  2 print(soup, type(soup))
获取标签Tag: soup.‘标签名‘ 就可以匹配出第一个该标签,它将会把第一次出现的该标签完整的返回。
  1 print(soup.span)
获取标签属性:
  1 print(type(soup.a))
  2 print(soup.a[‘id‘])   # 没有该属性会报错
  3 print(soup.a.attrs)     # 输出标签的属性和值
  4 print(soup.a.get(‘id‘))    # 推荐使用get取属性,没有返回None
代码的运行结构:
- <class ‘bs4.element.Tag‘>
- result_logo
- {‘href‘: ‘/‘, ‘id‘: ‘result_logo‘, ‘onmousedown‘: "return c({‘fm‘:‘tab‘,‘tab‘:‘logo‘})"}
- None
获取文档内容:获取到标签后(或者是soup),有几种不同的方法获取标签里的内容,分别如下:
strings: 直接加 .strings 返回的是一个生成器,但是作者不能调用next()方法,查询之后使用如下
    1 a = soup.div.strings
    2 a.__next__()
执行之后,可以再调用a.__next__(),这样会将文本内容一条条地返回,但是大多数时候,这样做是非常麻烦的。
    基于搜索方法find()和find_all()去获取文本内容:
字符串:soup.find_all(‘p‘) 获取所有的P标签,返回一个列表,soup.findl(‘p‘)只返回一个,类型为‘bs4.element.Tag‘
1 print(soup.find_all(‘p‘)[1])
2 print(soup.find_all(‘i‘, class_=‘c-icon-lidot‘)) # 限制属性class
字符串里只能是标签名,不能是其他内容,否则find_all()获取的是空列表,find()获取的是None
      find_all()获取的是列表元素也是类型为 ‘bs4.element.Tag‘ !
正则表达式:需要导入re,再用re.compile()根据包含的正则表达式的字符串创建模式对象。
    1 import re
    2 for i in soup.find_all(re.compile(‘span‘)):
    3         print(i.text) # 会将span标签内的所有文本内容返回
soup.find_all(re.compile(‘span‘))的元素仍然是‘bs4.element.Tag‘ !
列表:find_all方法也能接受列表参数,BeautifulSoup会将与列表中任一元素匹配的内容返回。
1 print(soup.find_all([‘i‘, ‘a‘])) # 获取所有的i标签和a标签
返回的数据类型为bs4.element.ResultSet,跟列表相似,可以通过索引取值且有序
      方法(调用函数体):如果没有合适的过滤器,我们也可以自定义一个方法,方法只接受一个元素参数。     
    1 def has_class_and_no_id(tag):
    2     return tag.has_attr(‘class‘) and not tag.has_attr(‘id‘)
    3 for tag in soup.find_all(has_class_and_no_id):
    4     print(tag)
    5 # soup.find_all(has_class_and_no_id)返回的数据类型是‘bs4.element.ResultSet‘
    6 # 同上,类似列表,可以索引取值且无序!
基于select获取:css选择器,写 CSS 时,标签名不加任何修饰,类名前加.,id名前加#;返回值是一个列表
标签名查找:soup.select(‘h3 a‘)取h3标签下的a标签;等价于soup.select(‘h3 > a‘)
     1 for i in soup.select(‘h3 a‘):
     2     # text取内容时返回的是str字符串
     3     result_1 = i.text
     4     # get_text取内容时返回的是str字符串
     5     result_2 = i.get_text()
     6     # string返回的是NavigableString,没有内容,将返回None
     7     result_3 = i.string
     8     # strings返回的是generator  如果内容为空,将返回None
     9     result_4 = i.strings
    10     print(result_1, type(result_1))
    11     print(result_2, type(result_2))
    12     print(result_3, type(result_3))
    13     print(result_4, type(result_4))
类名查找或id查找: soup.select(‘.c-gap-left-small‘) soup.select(‘#content_bottom‘)
组合查找: soup.select(‘a .c-gap-left-small‘)
搜索
