Python爬虫系列(六):搜索文档树

今天早上,写的东西掉了。这个烂知乎,有bug,说了自动保存草稿,其实并没有保存。无语

今晚,我们将继续讨论如何分析html文档。

1.字符串

#直接找元素

soup.find_all('b')

2.正则表达式

#通过正则找

import re

for tag in soup.find_all(re.compile("^b")):

print(tag.name)

3.列表

找a 和 b标签

soup.find_all(["a", "b"])

4.True

找所有标签

fortaginsoup.find_all(True):

print(tag.name)

5.方法

defhas_class_but_no_id(tag):

returntag.has_attr('class')andnottag.has_attr('id')

#调用外部方法。只返回方法满足为true的元素

soup.find_all(has_class_but_no_id)

6.find_all

ind_all() 方法搜索当前tag的所有tag子节点,并判断是否符合过滤器的条件.这里有几个例子:

soup.find_all("title")

#找class=title的p元素

soup.find_all("p", "title")

#找所有元素

soup.find_all("a")

#通过ID找

soup.find_all(id="link2")

#通过内容找

importre

soup.find(text=re.compile("sisters"))

#通过正则:查找元素属性满足条件的

soup.find_all(href=re.compile("elsie"))

#查找包含id的元素

soup.find_all(id=True)

#多条件查找

soup.find_all(href=re.compile("elsie"), id='link1')

有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性

data_soup = BeautifulSoup('

foo!
')

data_soup.find_all(data-foo="value")

但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag:

data_soup.find_all(attrs={"data-foo": "value"})

#按CSS搜索 注意class的用法

按照CSS类名搜索tag的功能非常实用,但标识CSS类名的关键字 class 在Python中是保留字,使用 class 做参数会导致语法错误.从Beautiful Soup的4.1.1版本开始,可以通过 class_ 参数搜索有指定CSS类名的tag

soup.find_all("a", class_="sister")

class_ 参数同样接受不同类型的 过滤器 ,字符串,正则表达式,方法或 True :

soup.find_all(class_=re.compile("itl"))

defhas_six_characters(css_class):

returncss_classisnotNoneandlen(css_class) == 6

soup.find_all(class_=has_six_characters)

tag的 class 属性是多值属性.按照CSS类名搜索tag时,可以分别搜索tag中的每个CSS类名:

css_soup = BeautifulSoup('')

css_soup.find_all("p", class_="strikeout")

css_soup.find_all("p", class_="body")

搜索 class 属性时也可以通过CSS值完全匹配

css_soup.find_all("p", class_="body strikeout")

完全匹配 class 的值时,如果CSS类名的顺序与实际不符,将搜索不到结果

soup.find_all("a", attrs={"class": "sister"})

通过 text 参数可以搜搜文档中的字符串内容.

与 name 参数的可选值一样, text 参数接受 字符串 , 正则表达式 , 列表, True .

soup.find_all(text="Elsie")

soup.find_all(text=["Tillie", "Elsie", "Lacie"])

soup.find_all(text=re.compile("Dormouse"))

def is_the_only_string_within_a_tag(s):

return (s == s.parent.string)

soup.find_all(text=is_the_only_string_within_a_tag)

虽然 text 参数用于搜索字符串,还可以与其它参数混合使用来过滤tag.Beautiful Soup会找到 .string 方法与 text 参数值相符的tag.下面代码用来搜索内容里面包含“Elsie”的标签

soup.find_all("a", text="Elsie")

find_all() 方法返回全部的搜索结构,如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果

soup.find_all("a", limit=2)

调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点,如果只想搜索tag的直接子节点,可以使用参数 recursive=False .

soup.html.find_all("title")

soup.html.find_all("title", recursive=False)

find_all() 几乎是Beautiful Soup中最常用的搜索方法,所以我们定义了它的简写方法. BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的

soup.find_all("a")

soup("a")

soup.title.find_all(text=True)

soup.title(text=True)

7.find

soup.find_all('title', limit=1)与soup.find('title')一样

find就是找到满足条件的第一个就返回。all返回列表,find返回一个对象

find_all() 方法没有找到目标是返回空列表, find() 方法找不到目标时,返回 None

soup.head.title 是 tag的名字 方法的简写.这个简写的原理就是多次调用当前tag的 find() 方法

soup.head.title与soup.find("head").find("title")

8.find_parents() 和 find_parent()

soup = BeautifulSoup(html_doc, "lxml")

a_string = soup.find(text="Lacie")

print('1---------------------------')

print(a_string)

print('2---------------------------')

#找直接父节点

print(a_string.find_parents("a"))

print('3---------------------------')

#迭代找父节点

print(a_string.find_parent("p"))

print('4---------------------------')

#找直接父节点

print(a_string.find_parents("p", class_="title"))

9.find_next_siblings() 合 find_next_sibling()

soup = BeautifulSoup(html_doc, "lxml")

a_string = soup.find(text="Lacie")

print('1---------------------------')

first_link = soup.a

print(first_link)

print('2---------------------------')

#找当前元素的所有后续元素

print(first_link.find_next_siblings("a"))

print('3---------------------------')

first_story_paragraph = soup.find("p", "story")

#找当前元素的紧接着的第一个元素

print(first_story_paragraph.find_next_sibling("p"))

10.find_previous_siblings() 和 find_previous_sibling()

和第9点方向相反

last_link = soup.find("a", id="link3")

last_link

last_link.find_previous_siblings("a")

first_story_paragraph = soup.find("p", "story")

first_story_paragraph.find_previous_sibling("p")

11.find_all_next() 和 find_next()

这2个方法通过 .next_elements 属性对当前tag的之后的tag和字符串进行迭代, find_all_next() 方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点:

first_link.find_all_next(text=True)

first_link.find_next("p")

12.find_all_previous() 和 find_previous()

这2个方法通过 .previous_elements 属性对当前节点前面 的tag和字符串进行迭代, find_all_previous() 方法返回所有符合条件的节点, find_previous() 方法返回第一个符合条件的节点

first_link.find_all_previous("p")

first_link.find_previous("title")

13.CSS选择器

查找class=title的元素

soup.select("title")

soup.select("p nth-of-type(3)")

通过元素层级查找

soup.select("body a")

soup.select("html head title")

找直接子元素

soup.select("head > title")

soup.select("p > a")

soup.select("p > a:nth-of-type(2)")

oup.select("p > #link1")

up.select("body > a")

找到兄弟节点标签

soup.select("#link1 ~ .sister")

soup.select("#link1 + .sister")

通过CSS的类名查找

soup.select(".sister")

这里的class没有加 _

soup.select("[class~=sister]")

通过tag的id查找

soup.select("#link1")

通过是否存在某个属性来查找

oup.select('a[href]')

通过属性的值来查找

soup.select('a[href="http://example.com/elsie"]')

#以title结尾

soup.select('a[href$="tillie"]')

#包含.com

soup.select('a[href*=".com/el"]')

通过语言设置来查找:就是通过元素属性来查找


multilingual_soup = BeautifulSoup(multilingual_markup)

multilingual_soup.select('p[lang|=en]')

这一部分内容,了解jquery的人一眼就看明白了

作为程序员,一定要学会触类旁通

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容