信息标记和提取
信息标记的三种形式
-
XML
最早的通用信息标记语言,可扩展性好,但繁琐。
主要用于 Internet 上的信息交互与传递。
-
JSON
信息有类型,适合程序处理(js),较 XML 简洁。
主要用于移动应用云端和节点的信息通信,缺点是无注释。
-
YAML
信息无类型,文本信息比例最高,如
name:silas
,没有引号标明是字符串。主要用于各类系统的配置文件,有注释易读。
-
缩进表达所属关系
name: newName: mzj oldName: myz
-
-
表达并列关系name: - mzj - myz
-
|
表达整块数据,#
表示注释text: | # 介绍 abcdefghijklmnopqrstuvwxyz0123456789
-
信息提取
soup = BeautifulSoup(res.text, 'html.parser')
# 搜索所有 <a> 标签内容
for link in soup.find_all('a'):
print(link.get('href'))
find_all(name, attrs, recursive, string, **kwargs)
返回一个列表类型,存储查找的结果
-
name:对标签名称的检索字符串
# 提取一个标签 soup.find_all('a') # 提取多个标签 soup.find_all(['a','div']) # 参数为 True 提取所有标签 for tag in soup.find_all(True): print(tag.name) # 提取所有匹配正则表达式(以 b 开头)的标签 import re for tag in soup.find_all(re.compile('b')): print(tag.name)
-
attrs:对标签属性值的检索字符串,可标注属性检索
所有
<a>
标签中有bri
属性的标签。>>> soup.find_all('a', 'bri') [<a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品</a>]
所有 id 为
lh
的标签>>> soup.find_all(id="lh") [<p id="lh"> <a href="http://home.baidu.com">关于百度</a> <a href="http://ir.baidu.com">About Baidu</a> </p>]
所有包含
link
文字的 id,比如link1
,alinkb
等>>> soup.find_all(id=re.compile('link')) []
-
recursive:是否对子孙全部检索,默认True
>>> soup.find_all('a')
[<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>, <a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>, <a class="mnav" href="http://map.baidu.com" name="tj_trmap">地图</a>, <a class="mnav" href="http://v.baidu.com" name="tj_trvideo">视频</a>, <a class="mnav" href="http://tieba.baidu.com" name="tj_trtieba">贴吧</a>, <a class="lb" href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1" name="tj_login">登录</a>, <a class="bri" href="//www.baidu.com/more/" name="tj_briicon" style="display: block;">更多产品</a>, <a href="http://home.baidu.com">关于百度</a>, <a href="http://ir.baidu.com">About Baidu</a>, <a href="http://www.baidu.com/duty/">使用百度前必读</a>, <a class="cp-feedback" href="http://jianyi.baidu.com/">意见反馈</a>]
>>> soup.find_all('a',recursive=False)
什么都没有,输出
[]
-
string: 对标签中字符串区域的检索字符串
文档中有
"> <a href="http://home.baidu.com">关于百度</a> <a href="http://ir.baidu.com">About Baidu</a>
这么一条>>> soup.find_all(string="关于百度") ['关于百度']
所有含有“百度”的内容
>>> soup.find_all(string=re.compile('百度')) ['百度一下,你就知道', '关于百度', '使用百度前必读']
简写:
<tag>()
等价 <tag>.find_all()
soup()
等价 soup.find_all()
扩展方法
方法 | 说明 |
---|---|
<>.find() |
搜索且只返回一个结果, 同 .find_all() 参数 |
<>.find_parents() |
在先辈节点中搜索,返回列表类型,同 .find_all() 参数 |
<>.find_parent() |
在先辈节点中返回一个结果,同 .find() 参数 |
<>.find_next_siblings() |
在后续平行节点中搜索,返回列表类型,同 .find_all() 参数 |
<>.find_next_sibling() |
在后续平行节点中返回一个结果,同 .find() 参数 |
<>.find_previous_siblings() |
在前序平行节点中搜索,返回列表类型,同 .find_all() 参数 |
<>.find_previous_sibling() |
在前序平行节点中返回一个结果,同 .find() 参数 |
实例
爬取 http://www.zuihaodaxue.cn/zuihaodaxuepaiming2018.html
的大学排名并提取信息。
思考步骤:
-
打开网页,查看源代码,查找一个大学,比如“清华大学”,定位到代码位置
university.png
一个
<tr>
包含一个大学,具体信息在<td>
标签中,前四个分别为大学排名,大学名称,所在城市,分数。 -
打开
http://www.zuihaodaxue.cn/robots.txt
看网站是否禁止爬取,结果是没有这个文件,所以可以爬取 -
定义输出结果,按排名、学校名称、总分排列
-
定义方法 getHTMLText() 爬取网页内容
-
定义方法 fillUnivList() 将网页内容提取到合适的数据结构中
-
定义方法 printUnivList() 将数据结构中内容输出显示
import requests
import bs4
def getHTMLText(url):
try:
res = requests.get(url, timeout=30)
res.raise_for_status()
res.encoding = res.apparent_encoding
return res.text
except:
return ""
def fillUnivList(ulist, html):
soup = bs4.BeautifulSoup(html, 'html.parser')
for tr in soup.find('tbody').children: # 遍历子节点,每个 tr 就是一所大学
if isinstance(tr, bs4.element.Tag): # 过滤掉不是标签类型的子节点
tds = tr('td') # 相当于 tr.find_all('td') 找 tr 里面的所有 td
ulist.append([tds[0].string, tds[1].string, tds[3].string])
def printUnivList(ulist, num):
tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
print(tplt.format("排名","学校名称","总分",chr(12288)))
for i in range(num):
u = ulist[i]
print(tplt.format(u[0],u[1],u[2],chr(12288)))
def main():
uinfo = [] # 存储大学信息的列表
url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2018.html'
html = getHTMLText(url)
fillUnivList(uinfo, html)
printUnivList(uinfo, 20) # 只打印前 20 名大学数据
main()
网友评论