复杂的HTML解析 003

当咱们想要从复杂的网络信息中抽取出咱们须要的信息时,不假思索的写出层层抽取的代码是很是不理智的。这样的代码又臭又长,难以阅读,且容易失效。正确的方法是三思然后行,使用正确的技巧方法写出简洁,易懂,扩展性强的代码。 重要的事情说三遍:三思然后行,三思然后行,三思然后行html

1.class和id抽取

网页的class属性和id属性是很是丰富的,咱们可使用这些属性来抽取信息: 例子:python

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://pythonscraping.com/pages/warandpeace.html")
#网页html代码赋给变量bs0bj
bs0bj = BeautifulSoup(html)
#返回一个含有class=green属性的列表
namelist = bs0bj.findAll("span",{"class":"green"})
#遍历输出列表中不含标签的文字。
for name in namelist:
	print(name.get_text())

.get_text():把正在处理的html文档中的全部标签都清除,返回一个只包含文字的字符串,通常状况下因尽量保留标签,在最后状况下使用get_text()。正则表达式

2.find()和finaall()

find()和finaall()这两个函数是很是经常使用的,咱们能够用它们找到须要的标签或标签组。 函数的格式定义以下:api

findAll(tag, attributes, recursive, text, limit, keywords)

find(tag, attributes, recursive, text, keywords)
  • tag:能够传入一个标签或多个标签的标签组,.findAll({"h1","h2","h3","h4","h5","h6"})
  • attributes:用一个字典封装的一个标签的若干属性和对应的属性值
  • recursive:是否递归查找子标签,默认为true,若是设置为False,则只查找一级标签。
  • text:用来匹配标签的文本内容,不是标签的属性,切记。
  • limit:限制数量,当为1时至关于find()函数,设置为n时,显示前n个,按在网页上的顺序排列显示。
  • keyword:选择具备指定属性的标签。

3.beautifulsoup对象

  • BeautifulSoup 对象:前面代码中的bsObj
  • Tag 对象 :前面代码中的bsObj.div.h1
  • NavigableString 对象:标签里的文字
  • comment 对象:查找html的注释标签, <!--like this one-->

4.导航树:

整个html页面能够简化为一棵树,以下所示:网络

输入图片说明

输入图片说明

1.处理子标签和后代标签:函数

通常状况下,beautifulsoup老是处理当前标签下的后代标签,如bs0bj.body.h1是处理当前body标签下的第一个h1标签。bs0bj.body.finaAll("img")是找到第一div标签下的索引img列表。学习

若是只想要找到子标签,可使用.children标签。测试

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for child in bsObj.find("table",{"id":"giftList"}).children:
    print(child)

上面的代码会打印giftlist表格中的索引产品的数据行。this

使用descendants()标签能够输出全部的后代标签。url

2.兄弟标签: 使用next_siblings()函数能够处理兄弟标签。

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
for sibling in bsObj.find("table",{"id":"giftList"}).tr.next_siblings:
print(sibling)

使用兄弟标签会跳过标签自身,由于自身不能看成本身的兄弟,同时兄弟标签只能查找后面的标签,不能查找自身以及前面的兄弟标签。

与next_siblings()相似,previous_siblings()函数是查找前面的兄弟节点。

同时还有next_siblings()和previous_siblings()函数,它们的做业是返回单个标签。

3.父标签

使用parent和parents标签能够查找给定标签的父标签或父标签列表。

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
print(bsObj.find("img",{"src":"../img/gifts/img1.jpg" 
}).parent.previous_sibling.get_text())

上面代码的意思是找到给定标签的父标签的前一个兄弟标签中的文字。

5.正则表达式:

正则表达式是很是丰富的,可是上手很简单。能够本身搜索一些教程学习。 正则测试:http://www.regexpal.com/

6.正则表达式与BeautifulSoup

正则表达式是很是有用的,举个例子,加入你想要抓取索引的img图片,使用finaall()获得的结果可能会出乎意料,多了许多隐藏的图片或不相关的图片,此时可使用正则表达式。咱们发现想要获取的图片源代码格式以下:

<img src="../img/gifts/img3.jpg">

这样咱们能够直接经过文件路径来查找信息,

from urllib.request
import urlopenfrom bs4
import BeautifulSoupimport re

html = urlopen("http://www.pythonscraping.com/pages/page3.html")
bsObj = BeautifulSoup(html)
images = bsObj.findAll("img", {"src":re.compile("\.\.\/img\/gifts/img.*\.jpg")})
for image in images:
    print(image["src"])

上面的例子使用了正则表达式匹配了以../img/gifts/img开头,以.jpg结尾的图片。结果以下:

../img/gifts/img1.jpg
../img/gifts/img2.jpg
../img/gifts/img3.jpg
../img/gifts/img4.jpg
../img/gifts/img6.jpg

6.标签属性:

对于一个标签对象,可使用下面代码得到它的所有属性:

myTag.attrs

得到的属性存在一个字典中,能够取出某一个属性

myTag.attrs["href"]

7.lambda表达式

相关文章
相关标签/搜索