python爬虫:BeautifulSoup 使用select方法的使用


 1 html = """
 2 <html><head><title>The Dormouse's storytitle>head>
 3 <body>
 4 <p class="title" name="dromouse"><b>The Dormouse's storyb>p>
 5 <p class="story">Once upon a time there were three little sisters; and their names were
 6 <a href="http://example.com/elsie" class="sister" id="link1">a>,
 7 <a href="http://example.com/lacie" class="sister" id="link2">Laciea> and
 8 <a href="http://example.com/tillie" class="sister" id="link3">Tilliea>;
 9 and they lived at the bottom of a well.p>
10 <p class="story">...p>
11 """
复制代码

 

我们在写 CSS 时,标签名不加任何修饰,类名(class="className"引号内即为类名)前加点,id名(id="idName"引号前即为id名)前加 #,在这里我们也可以利用类似的方法来筛选元素,用到的方法是 soup.select(),返回类型是 list
(1)通过标签名查找
 

print soup.select('title') 
#[The Dormouse's story]
 
print soup.select('a')
#[, Lacie, Tillie]
 
print soup.select('b')
#[The Dormouse's story]

(2)通过类名查找
 

print soup.select('.sister')
#[, Lacie, Tillie]

(3)通过 id 名查找
 

print soup.select('#link1')
#[]

(4)组合查找

组合查找即和写 class 文件时,标签名与类名、id名进行的组合原理是一样的,例如查找 p 标签中,id 等于 link1的内容,二者需要用空格分开
 

print soup.select('p #link1')
#[]

直接子标签查找
 

print soup.select("head > title")
#[The Dormouse's story]

(5)属性查找

查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。
 

print soup.select("head > title")
#[The Dormouse's story]
 
print soup.select('a[href="http://example.com/elsie"]')
#[]

同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格
 

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

 

BeautifulSoup支持CSS选择器是令人惊喜的,这大大方便了我们对特定标签的选取。那么接下来就来试验一下。 
比如现在我们需要选取搜狗主页中导航栏中导向“知乎”的链接。 
分析文档结构大概有这几个比较容易区分的层级特点:

<div class="top-nav">
    <ul>
        ...
        <li class="cur"><span>网页span>li>
        href="http://zhihu.sogou.com/" uigs-id="nav_zhihu" id="zhihu">知乎a>li>
        <li><a onclick="st(this,'40030500','pic')" href="http://pic.sogou.com" uigs-id="nav_pic" id="pic">图片a>li>
        ...
    ul>
div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

鉴于如此的结构,我们可以使用类选择器选择“.top-nav”然后使用后代选择其选择“ul”标签和“li”标签,于是整个选择器可以写为“.top-nav ul li”,在代码中实现如下:

li = bs.select('.top-nav ul li')
print("result len is", len(li))
for tag in li:
    print(tag)
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

得到如下输出:

result len is 10
<li><a href="http://news.sogou.com" id="news" onclick="st(this,'40030300','news')" uigs-id="nav_news">新闻a>li>
<li class="cur"><span>网页span>li>
<li><a href="http://weixin.sogou.com/" id="weixinch" onclick="st(this,'73141200','weixin')" uigs-id="nav_weixin">微信a>li>
<li><a href="http://zhihu.sogou.com/" id="zhihu" onclick="st(this,'40051200','zhihu')" uigs-id="nav_zhihu">知乎a>li>
<li><a href="http://pic.sogou.com" id="pic" onclick="st(this,'40030500','pic')" uigs-id="nav_pic">图片a>li>
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

但里面出现了“网页”这个没有链接到其他地址的项,要如何将之过滤掉呢。可以结合filter函数进行处理,如下:

def hasHttpLink(tag):
    """此时的tag为
  • 标签,需要取得其中的再来进行判断""" return tag.a is not None and tag.a.get('href').startswith("http") for tag in filter(hasHttpLink, li): print(tag)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    结果中已经过滤掉“网页”这项了:

    <li><a href="http://news.sogou.com" id="news" onclick="st(this,'40030300','news')" uigs-id="nav_news">新闻a>li>
    <li><a href="http://weixin.sogou.com/" id="weixinch" onclick="st(this,'73141200','weixin')" uigs-id="nav_weixin">微信a>li>
    <li><a href="http://zhihu.sogou.com/" id="zhihu" onclick="st(this,'40051200','zhihu')" uigs-id="nav_zhihu">知乎a>li>
    <li><a href="http://pic.sogou.com" id="pic" onclick="st(this,'40030500','pic')" uigs-id="nav_pic">图片a>li>
    ...
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    其中filter高阶函数进行过滤时还可以使用正则来进行匹配筛选。 
    不过一般情况下仅仅使用selector就能比较精确的获取结果集了,因此filter也不用写得很复杂。


    你可能感兴趣的:(python与爬虫)