1. 程式人生 > >Python爬蟲---提取資料(2)--beautifulsoup

Python爬蟲---提取資料(2)--beautifulsoup

Beautiful Soup

是一個可以從HTML或XML檔案中提取資料的Python庫.它能夠通過你喜歡的轉換器實現慣用的文件導航,查詢,修改文件的方式.Beautiful Soup會幫你節省數小時甚至數天的工作時間.
文件地址:http://beautifulsoup.readthedocs.io/zh_CN/latest/
安裝:
apt-get install Python-bs4

Beautiful Soup 4 通過PyPi釋出,所以如果你無法使用系統包管理安裝,那麼也可以通過 easy_install 或 pip 來安裝.包的名字是 beautifulsoup4 ,這個包相容Python2和Python3.

$ easy_install beautifulsoup4

$ pip install beautifulsoup4

依賴的解析器安裝:
安裝解析器
Beautiful Soup支援Python標準庫中的HTML解析器,還支援一些第三方的解析器,其中一個是 lxml .根據作業系統不同,可以選擇下列方法來安裝lxml:

$ apt-get install Python-lxml

$ easy_install lxml

$ pip install lxml

另一個可供選擇的解析器是純Python實現的 html5lib , html5lib的解析方式與瀏覽器相同,可以選擇下列方法來安裝html5lib:

$ apt-get install Python-html5lib

$ easy_install html5lib

$ pip install html5lib
推薦使用lxml作為解析器,因為效率更高. 在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必須安裝lxml或html5lib, 因為那些Python版本的標準庫中內建的HTML解析方法不夠穩定.

下面開始使用這個庫(這裡之講解簡單的用法,具體看文件)

1.建立 Beautiful Soup 物件
首先必須要匯入 bs4 庫

<python>
#coding:utf-8
from bs4 import BeautifulSoup
import lxml
</python>

例項化Beautifulsoup ,建立物件
一段html程式碼(可以是抓取的也可以是寫入的),也可以從檔案裡面。

<python>
html='''
一段html程式碼
'''
soup = BeautifulSoup(html)
soup = BeautifulSoup(open('百度一下,你就知道.html'))
</python>

修改一下:後面新增lxml,表示用lxml解析器
soup = BeautifulSoup(open(‘baidu.html’),”lxml”)

這裡載入百度首頁檔案:
可以嘗試輸出:

<python>
print soup #普通輸出
print soup.prettify() #格式化輸出
</python>

格式化輸出結果:

<html>
</html>

四大物件種類

Beautiful Soup將複雜HTML文件轉換成一個複雜的樹形結構,每個節點都是Python物件,所有物件可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment .

(1)Tag

Tag 是什麼?通俗點講就是 HTML 中的一個個標籤,例如:

<title>The Dormouse's story</title>
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

上面的 title a 等等 HTML 標籤加上裡面包括的內容就是 Tag,下面我們來感受一下怎樣用 Beautiful Soup 來方便地獲取 Tags

下面每一段程式碼中註釋部分即為執行結果

print soup.title
#<title>The Dormouse's story</title>

print soup.head
#<head><title>The Dormouse's story</title></head>

print soup.a
#<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>

print soup.p
#<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

我們可以利用 soup加標籤名輕鬆地獲取這些標籤的內容,是不是感覺比正則表示式方便多了?不過有一點是,它查詢的是在所有內容中的第一個符合要求的標籤,如果要查詢所有的標籤,我們在後面進行介紹。
我們可以驗證一下這些物件的型別

print type(soup.a)
#<class 'bs4.element.Tag'>

對於 Tag,它有兩個重要的屬性,是 name 和 attrs,下面我們分別來感受一下:

name

print soup.name
print soup.head.name
#[document]
#head

soup 物件本身比較特殊,它的 name 即為 [document],對於其他內部標籤,輸出的值便為標籤本身的名稱。

attrs

print soup.p.attrs
#{'class': ['title'], 'name': 'dromouse'}

在這裡,我們把 p 標籤的所有屬性列印輸出了出來,得到的型別是一個字典。

如果我們想要單獨獲取某個屬性,可以這樣,例如我們獲取它的 class 叫什麼

print soup.p['class']
#['title']

還可以這樣,利用get方法,傳入屬性的名稱,二者是等價的

print soup.p.get('class')
#['title']

我們可以對這些屬性和內容等等進行修改,例如

soup.p['class']="newClass"
print soup.p
#<p class="newClass" name="dromouse"><b>The Dormouse's story</b></p>

還可以對這個屬性進行刪除,例如

del soup.p['class']
print soup.p
#<p name="dromouse"><b>The Dormouse's story</b></p>

不過,對於修改刪除的操作,不是我們的主要用途,在此不做詳細介紹了,如果有需要,請檢視前面提供的官方文件
(2)NavigableString

既然我們已經得到了標籤的內容,那麼問題來了,我們要想獲取標籤內部的文字怎麼辦呢?很簡單,用 .string 即可,例如

print soup.p.string
#The Dormouse's story

這樣我們就輕鬆獲取到了標籤裡面的內容,想想如果用正則表示式要多麻煩。它的型別是一個 NavigableString,翻譯過來叫 可以遍歷的字串,不過我們最好還是稱它英文名字吧。

print type(soup.p.string)
#<class 'bs4.element.NavigableString'>

來檢查一下它的型別

print type(soup.p.string)
#<class 'bs4.element.NavigableString'>

(3)BeautifulSoup

BeautifulSoup 物件表示的是一個文件的全部內容.大部分時候,可以把它當作 Tag 物件,是一個特殊的 Tag,我們可以分別獲取它的型別,名稱,以及屬性來感受一下

print type(soup.name)
#<type 'unicode'>
print soup.name 
# [document]
print soup.attrs 
#{} 空字典

(4)Comment

Comment 物件是一個特殊型別的 NavigableString 物件,其實輸出的內容仍然不包括註釋符號,但是如果不好好處理它,可能會對我們的文字處理造成意想不到的麻煩。

我們找一個帶註釋的標籤

print soup.a
print soup.a.string
print type(soup.a.string)

執行結果如下

<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
 Elsie 
<class 'bs4.element.Comment'>

a 標籤裡的內容實際上是註釋,但是如果我們利用 .string 來輸出它的內容,我們發現它已經把註釋符號去掉了,所以這可能會給我們帶來不必要的麻煩。

另外我們列印輸出下它的型別,發現它是一個 Comment 型別,所以,我們在使用前最好做一下判斷,判斷程式碼如下

if type(soup.a.string)==bs4.element.Comment:
print soup.a.string

上面的程式碼中,我們首先判斷了它的型別,是否為 Comment 型別,然後再進行其他操作,如列印輸出。
6. 遍歷文件樹
(1)直接子節點

要點:.contents .children 屬性

.contents

tag 的 .content 屬性可以將tag的子節點以列表的方式輸出

print soup.head.contents 
#[<title>The Dormouse's story</title>]

輸出方式為列表,我們可以用列表索引來獲取它的某一個元素

print soup.head.contents[0]
#<title>The Dormouse's story</title>

.children

它返回的不是一個 list,不過我們可以通過遍歷獲取所有子節點。

我們列印輸出 .children 看一下,可以發現它是一個 list 生成器物件

print soup.head.children
#<listiterator object at 0x7f71457f5710>

我們怎樣獲得裡面的內容呢?很簡單,遍歷一下就好了,程式碼及結果如下

for child in soup.body.children:
print child

<p class="title" name="dromouse"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>

(2)所有子孫節點

知識點:.descendants 屬性

.descendants

.contents 和 .children 屬性僅包含tag的直接子節點,.descendants 屬性可以對所有tag的子孫節點進行遞迴迴圈,和 children類似,我們也需要遍歷獲取其中的內容。

for child in soup.descendants:
print child

執行結果如下,可以發現,所有的節點都被打印出來了,先生最外層的 HTML標籤,其次從 head 標籤一個個剝離,以此類推。

<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body></html>
<head><title>The Dormouse's story</title></head>
<title>The Dormouse's story</title>
The Dormouse's story

<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
</body>

<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<b>The Dormouse's story</b>
The Dormouse's story

<p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
Once upon a time there were three little sisters; and their names were

<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
 Elsie 

,

<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
Lacie
 and

<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
Tillie
;
and they lived at the bottom of a well.

<p class="story">...</p>
...

(3)節點內容

知識點:.string 屬性

如果tag只有一個 NavigableString 型別子節點,那麼這個tag可以使用 .string 得到子節點。如果一個tag僅有一個子節點,那麼這個tag也可以使用 .string 方法,輸出結果與當前唯一子節點的 .string 結果相同。

通俗點說就是:如果一個標籤裡面沒有標籤了,那麼 .string 就會返回標籤裡面的內容。如果標籤裡面只有唯一的一個標籤了,那麼 .string 也會返回最裡面的內容。例如

print soup.head.string
#The Dormouse's story
print soup.title.string
#The Dormouse's story

如果tag包含了多個子節點,tag就無法確定,string 方法應該呼叫哪個子節點的內容, .string 的輸出結果是 None

print soup.html.string
# None

(4)多個內容

知識點: .strings .stripped_strings 屬性

.strings

獲取多個內容,不過需要遍歷獲取,比如下面的例子

for string in soup.strings:
  print(repr(string))
  # u"The Dormouse's story"
  # u'\n\n'
  # u"The Dormouse's story"
  # u'\n\n'
  # u'Once upon a time there were three little sisters; and their names were\n'
  # u'Elsie'
  # u',\n'
  # u'Lacie'
  # u' and\n'
  # u'Tillie'
  # u';\nand they lived at the bottom of a well.'
  # u'\n\n'
  # u'...'
  # u'\n'

.stripped_strings

輸出的字串中可能包含了很多空格或空行,使用 .stripped_strings 可以去除多餘空白內容

for string in soup.stripped_strings:
  print(repr(string))
  # u"The Dormouse's story"
  # u"The Dormouse's story"
  # u'Once upon a time there were three little sisters; and their names were'
  # u'Elsie'
  # u','
  # u'Lacie'
  # u'and'
  # u'Tillie'
  # u';\nand they lived at the bottom of a well.'
  # u'...'

(5)父節點

知識點: .parent 屬性

p = soup.p
print p.parent.name
#body

content = soup.head.title.string
print content.parent.name
#title

(6)全部父節點

知識點:.parents 屬性

通過元素的 .parents 屬性可以遞迴得到元素的所有父輩節點,例如

content = soup.head.title.string
for parent in content.parents:
  print parent.name



title
head
html
[document]

(7)兄弟節點

知識點:.next_sibling .previous_sibling 屬性

兄弟節點可以理解為和本節點處在統一級的節點,.next_sibling 屬性獲取了該節點的下一個兄弟節點,.previous_sibling 則與之相反,如果節點不存在,則返回 None

注意:實際文件中的tag的 .next_sibling 和 .previous_sibling 屬性通常是字串或空白,因為空白或者換行也可以被視作一個節點,所以得到的結果可能是空白或者換行

print soup.p.next_sibling
#    實際該處為空白
print soup.p.prev_sibling
#None  沒有前一個兄弟節點,返回 None
print soup.p.next_sibling.next_sibling
#<p class="story">Once upon a time there were three little sisters; and their names were
#<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>,
#<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
#<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
#and they lived at the bottom of a well.</p>
#下一個節點的下一個兄弟節點是我們可以看到的節點

(8)全部兄弟節點

知識點:.next_siblings .previous_siblings 屬性

通過 .next_siblings 和 .previous_siblings 屬性可以對當前節點的兄弟節點迭代輸出

for sibling in soup.a.next_siblings:
  print(repr(sibling))
  # u',\n'
  # <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>
  # u' and\n'
  # <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
  # u'; and they lived at the bottom of a well.'
  # None

(9)前後節點

知識點:.next_element .previous_element 屬性

與 .next_sibling .previous_sibling 不同,它並不是針對於兄弟節點,而是在所有節點,不分層次

比如 head 節點為

 <head><title>The Dormouse's story</title></head>

那麼它的下一個節點便是 title,它是不分層次關係的

print soup.head.next_element
#<title>The Dormouse's story</title>

(10)所有前後節點

知識點:.next_elements .previous_elements 屬性

通過 .next_elements 和 .previous_elements 的迭代器就可以向前或向後訪問文件的解析內容,就好像文件正在被解析一樣

for element in last_a_tag.next_elements:
  print(repr(element))
# u'Tillie'
# u';\nand they lived at the bottom of a well.'
# u'\n\n'
# <p class="story">...</p>
# u'...'
# u'\n'
# None

7.搜尋文件樹
(1)find_all( name , attrs , recursive , text , **kwargs )

find_all() 方法搜尋當前tag的所有tag子節點,並判斷是否符合過濾器的條件

1)name 引數

name 引數可以查詢所有名字為 name 的tag,字串物件會被自動忽略掉

A.傳字串

最簡單的過濾器是字串.在搜尋方法中傳入一個字串引數,Beautiful Soup會查詢與字串完整匹配的內容,下面的例子用於查詢文件中所有的
標籤
soup.find_all(‘b’)
# [The Dormouse’s story]

print soup.find_all('a')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

B.傳正則表示式

如果傳入正則表示式作為引數,Beautiful Soup會通過正則表示式的 match() 來匹配內容.下面例子中找出所有以b開頭的標籤,這表示和標籤都應該被找到

import re
for tag in soup.find_all(re.compile("^b")):
  print(tag.name)
# body
# b

C.傳列表

如果傳入列表引數,Beautiful Soup會將與列表中任一元素匹配的內容返回.下面程式碼找到文件中所有標籤和標籤

soup.find_all(["a", "b"])
# [<b>The Dormouse's story</b>,
# <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

D.傳 True

True 可以匹配任何值,下面程式碼查詢到所有的tag,但是不會返回字串節點

for tag in soup.find_all(True):
  print(tag.name)
# html
# head
# title
# body
# p
# b
# p
# a
# a

E.傳方法

如果沒有合適過濾器,那麼還可以定義一個方法,方法只接受一個元素引數 [4] ,如果這個方法返回 True 表示當前元素匹配並且被找到,如果不是則反回 False

下面方法校驗了當前元素,如果包含 class 屬性卻不包含 id 屬性,那麼將返回 True:

def has_class_but_no_id(tag):
  return tag.has_attr('class') and not tag.has_attr('id')

將這個方法作為引數傳入 find_all() 方法,將得到所有

標籤:

soup.find_all(has_class_but_no_id)
# [<p class="title"><b>The Dormouse's story</b></p>,
# <p class="story">Once upon a time there were...</p>,
# <p class="story">...</p>]

2)keyword 引數

注意:如果一個指定名字的引數不是搜尋內建的引數名,搜尋時會把該引數當作指定名字tag的屬性來搜尋,如果包含一個名字為 id 的引數,Beautiful Soup會搜尋每個tag的”id”屬性

soup.find_all(id='link2')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

如果傳入 href 引數,Beautiful Soup會搜尋每個tag的”href”屬性

soup.find_all(href=re.compile("elsie"))
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

使用多個指定名字的引數可以同時過濾tag的多個屬性

soup.find_all(href=re.compile("elsie"), id='link1')
# [<a class="sister" href="http://example.com/elsie" id="link1">three</a>]

在這裡我們想用 class 過濾,不過 class 是 python 的關鍵詞,這怎麼辦?加個下劃線就可以

soup.find_all("a", class_="sister")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

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

soup.find_all("a", class_="sister")
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
# <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

但是可以通過 find_all() 方法的 attrs 引數定義一個字典引數來搜尋包含特殊屬性的tag

data_soup.find_all(attrs={"data-foo": "value"})
# [<div data-foo="value">foo!</div>]

3)text 引數

通過 text 引數可以搜搜文件中的字串內容.與 name 引數的可選值一樣, text 引數接受 字串 , 正則表示式 , 列表, True

soup.find_all(text="Elsie")
# [u'Elsie']

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

soup.find_all(text=re.compile("Dormouse"))
[u"The Dormouse's story", u"The Dormouse's story"]

4)limit 引數

find_all() 方法返回全部的搜尋結構,如果文件樹很大那麼搜尋會很慢.如果我們不需要全部結果,可以使用 limit 引數限制返回結果的數量.效果與SQL中的limit關鍵字類似,當搜尋到的結果數量達到 limit 的限制時,就停止搜尋返回結果.

文件樹中有3個tag符合搜尋條件,但結果只返回了2個,因為我們限制了返回數量

soup.find_all("a", limit=2)
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
# <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

5)recursive 引數

呼叫tag的 find_all() 方法時,Beautiful Soup會檢索當前tag的所有子孫節點,如果只想搜尋tag的直接子節點,可以使用引數 recursive=False .

一段簡單的文件:

複製程式碼 程式碼如下:

 <html>
  <head>
   <title>
    The Dormouse's story
   </title>
  </head>
 ...

是否使用 recursive 引數的搜尋結果:

soup.html.find_all("title")
# [<title>The Dormouse's story</title>]

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

(2)find( name , attrs , recursive , text , **kwargs )

它與 find_all() 方法唯一的區別是 find_all() 方法的返回結果是值包含一個元素的列表,而 find() 方法直接返回結果
(3)find_parents() find_parent()

find_all() 和 find() 只搜尋當前節點的所有子節點,孫子節點等. find_parents() 和 find_parent() 用來搜尋當前節點的父輩節點,搜尋方法與普通tag的搜尋方法相同,搜尋文件搜尋文件包含的內容
(4)find_next_siblings() find_next_sibling()

這2個方法通過 .next_siblings 屬性對當 tag 的所有後面解析的兄弟 tag 節點進行迭代, find_next_siblings() 方法返回所有符合條件的後面的兄弟節點,find_next_sibling() 只返回符合條件的後面的第一個tag節點
(5)find_previous_siblings() find_previous_sibling()

這2個方法通過 .previous_siblings 屬性對當前 tag 的前面解析的兄弟 tag 節點進行迭代, find_previous_siblings() 方法返回所有符合條件的前面的兄弟節點, find_previous_sibling() 方法返回第一個符合條件的前面的兄弟節點
(6)find_all_next() find_next()

這2個方法通過 .next_elements 屬性對當前 tag 的之後的 tag 和字串進行迭代, find_all_next() 方法返回所有符合條件的節點, find_next() 方法返回第一個符合條件的節點
(7)find_all_previous() 和 find_previous()

這2個方法通過 .previous_elements 屬性對當前節點前面的 tag 和字串進行迭代, find_all_previous() 方法返回所有符合條件的節點, find_previous()方法返回第一個符合條件的節點

注:以上(2)(3)(4)(5)(6)(7)方法引數用法與 find_all() 完全相同,原理均類似,在此不再贅述。

8.CSS選擇器

我們在寫 CSS 時,標籤名不加任何修飾,類名前加點,id名前加 #,在這裡我們也可以利用類似的方法來篩選元素,用到的方法是 soup.select(),返回型別是 list
(1)通過標籤名查詢

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

print soup.select('a')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

print soup.select('b')
#[<b>The Dormouse's story</b>]

(2)通過類名查詢

print soup.select('.sister')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

(3)通過 id 名查詢

print soup.select('#link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

(4)組合查詢

組合查詢即和寫 class 檔案時,標籤名與類名、id名進行的組合原理是一樣的,例如查詢 p 標籤中,id 等於 link1的內容,二者需要用空格分開

print soup.select('p #link1')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

直接子標籤查詢

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

(5)屬性查詢

查詢時還可以加入屬性元素,屬性需要用中括號括起來,注意屬性和標籤屬於同一節點,所以中間不能加空格,否則會無法匹配到。

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

print soup.select('a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

同樣,屬性仍然可以與上述查詢方式組合,不在同一節點的空格隔開,同一節點的不加空格

print soup.select('p a[href="http://example.com/elsie"]')
#[<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>]

好,這就是另一種與 find_all 方法有異曲同工之妙的查詢方法

相關推薦

Python爬蟲---提取資料2--beautifulsoup

Beautiful Soup 是一個可以從HTML或XML檔案中提取資料的Python庫.它能夠通過你喜歡的轉換器實現慣用的文件導航,查詢,修改文件的方式.Beautiful Soup會幫你節省數小時甚至數天的工作時間. 文件地址:http://beaut

python爬蟲讀書筆記2

1.網站地圖爬蟲 def crawl_sitemap(url): #下載網站地圖檔案 sitemap=download(url) #正則表示式,從<loc>標籤中提取出URL,獲得網站地圖連結 links=re.findall('<loc>

吳裕雄 python oracle檢索資料2

import cx_Oracle conn = cx_Oracle.connect("scott/[email protected]:1521/orcl")cursor = conn.cursor() sql = "select ascii('Z'),ascii('H'),ascii('D'),

爬蟲開發python工具包介紹 2

dir 部分 loop 網易 pat 選擇 服務器 mode follow 本文來自網易雲社區作者:王濤可選參數我們一一介紹一下:參數釋義示例params生成url中?號後面的查詢Key=value示例1: >>>payload = {‘key1‘: ‘v

python爬蟲入門八:多程序/多執行緒 python佇列Queue Python多執行緒(2)——執行緒同步機制 python學習筆記——多程序中共享記憶體Value & Array python 之 多程序 Python多程序 Python 使用multiprocessing 特別耗記

什麼是多執行緒/多程序 引用蟲師的解釋: 計算機程式只不過是磁碟中可執行的,二進位制(或其它型別)的資料。它們只有在被讀取到記憶體中,被作業系統呼叫的時候才開始它們的生命期。 程序(有時被稱為重量級程序)是程式的一次執行。每個程序都有自己的地址空間,記憶體,資料棧以及其它記錄其執行軌跡的輔助資料

node.js 小爬蟲抓取網頁資料2

node.js 小爬蟲抓取網頁資料 在原來的基礎上,採用了promise的模組,使其可以一次性多頁面的爬取網頁資料。 var http = require('http') var Promise = require('promise') var cheerio = re

python3實現網路爬蟲2--BeautifulSoup使用1

這一次我們來了解一下美味的湯--BeautifulSoup,這將是我們以後經常使用的一個庫,並且非常的好用。 BeautifuleSoup庫的名字取自劉易斯·卡羅爾在《愛麗絲夢遊仙境》裡的同名詩歌。在故事中,這首歌是素甲魚唱的。就像它在仙境中的說法一樣,BeautifulS

一個鹹魚的Python爬蟲之路:爬取網頁圖片

you os.path odin 路徑 生成 存在 parent lose exist 學完Requests庫與Beautifulsoup庫我們今天來實戰一波,爬取網頁圖片。依照現在所學只能爬取圖片在html頁面的而不能爬取由JavaScript生成的圖。所以我找了這個網站

Python爬蟲小白---爬蟲基礎--Selenium PhantomJS

decode bject windows beautiful 結構 由於 target header 速度 一、前言    前段時間嘗試爬取了網易雲音樂的歌曲,這次打算爬取QQ音樂的歌曲信息。網易雲音樂歌曲列表是通過iframe展示的,可以借助Selenium獲

python--DenyHttp項目2--ACM監考客戶端測試版1階段完成總結

tdi text class 測試版 window etl operate comm decode   客戶端: ‘‘‘ DenyManager.py 調用客戶端與客戶端界面 ‘‘‘ from DenyClient import * from DenyGui import

我的第一個python web開發框架2——一個簡單的小外包

span 技術 進行 target 最好 自己 blog height 描述   第一部分說明   第一部分大概有20來章,主要講的是一些開發常識、開發前中後期準備內容、開發環境與服務器部署環境安裝設置、python基礎框架結構與功能等內容,代碼會比較簡單。   

Python爬蟲實例爬取百度貼吧帖子中的圖片

選擇 圖片查看 負責 targe mpat wid agent html headers 程序功能說明:爬取百度貼吧帖子中的圖片,用戶輸入貼吧名稱和要爬取的起始和終止頁數即可進行爬取。 思路分析: 一、指定貼吧url的獲取 例如我們進入秦時明月吧,提取並分析其有效url如下

Python爬蟲實例使用selenium抓取鬥魚直播平臺數據

def 獲取 平臺 es2017 抓取 設置 log ips driver 程序說明:抓取鬥魚直播平臺的直播房間號及其觀眾人數,最後統計出某一時刻的總直播人數和總觀眾人數。 過程分析: 一、進入鬥魚首頁http://www.douyu.com/directory/all 進

Python爬蟲實例代理的使用

pen .sh strong list blank 寫入 禁止 bsp open() 一些網站會有相應的反爬蟲措施,例如很多網站會檢測某一段時間某個IP的訪問次數,如果訪問頻率太快以至於看起來不像正常訪客,它可能就會會禁止這個IP的訪問。所以我們需要設置一些代理服務器,每隔

Python爬蟲實例網站模擬登陸

opener 運行 webkit zh-cn head window targe Coding 破解 一、獲取一個有登錄信息的Cookie模擬登陸 下面以人人網為例,首先使用自己的賬號和密碼在瀏覽器登錄,然後通過抓包拿到cookie,再將cookie放到請求之中發送請求即可

Python叠代器2 —— 實現for循環

auth style code true next() logs div nbsp while Python的for循環本質上就是通過不斷調用next()函數實現的,例如: 1 #_*_coding:utf-8_*_ 2 #__author__ = "csy" 3

Python 爬蟲實例7—— 爬取 新浪軍事新聞

secure host agen cat hand .com cati ica sts 我們打開新浪新聞,看到頁面如下,首先去爬取一級 url,圖片中藍色圓圈部分 第二zh張圖片,顯示需要分頁,

Python 爬蟲實例10—— 四行代碼實現刷 博客園 閱讀數量

體會 博客 http log 實例 代碼 port 代碼實現 ive 代碼很少,自己去體會 from selenium import webdrever driver = webdrever.Chrome() url = "http://www.cnblo

Python 爬蟲實例12—— python selenium 爬蟲

bsp ide doc wid environ att fig exc title # coding:utf-8 from common.contest import * def spider():  url = "http://www.salamoyua.

caffe的python接口學習2生成solver文件

慢慢 oot __name__ nap gpu 計算 snapshot pro copy caffe在訓練的時候,需要一些參數設置,我們一般將這些參數設置在一個叫solver.prototxt的文件裏面 有一些參數需要計算的,也不是亂設置。 假設我們有50000個訓練樣本