爬蟲筆記-01-爬蟲介紹和BeautifulSoup

介紹

一直想有時間學(xué)習(xí)爬蟲技術(shù),現(xiàn)在來吧,跟著OReilly 出版的Web Scraping with Python 這本書來學(xué)習(xí)。

環(huán)境準(zhǔn)備

因為本書推薦Python3為例,去官網(wǎng)下載Python3.x版本的Python安裝包,直接安裝就好了。安裝的時候注意勾選加入path

話說我還沒有學(xué)Python呢親( ⊙ o ⊙ )!,沒關(guān)系先稀里糊涂的用吧~~~ 不行了再說

第一只爬蟲

書中首先做了一些介紹,主要內(nèi)容是網(wǎng)絡(luò)傳輸?shù)倪^程,說白了就是web交互其實可以跟瀏覽器沒有啥關(guān)系,而爬蟲就是不通過瀏覽器從服務(wù)端去爬數(shù)據(jù)...

初見

ok閑言碎語不要講來寫爬蟲吧
新建一個文件夾,里面建一個test.py文件,在里面寫入:

from urllib.request import urlopen
html = urlopen("http://pythonscraping.com/pages/page1.html")
print(html.read())

據(jù)說Python是一個很矯情的對空格、縮進(jìn)敏感的語言..所以一定要注意不要亂打空格和縮進(jìn)
保存,然后命令行cd到這個文件的目錄:

phython test.py

可以看到打印出來的html

美麗的湯

BeautifulSoup是一個lib,用來更好的解析html和xml的。

安裝湯

python3自帶了pip所以可以直接用pip安裝

pip install beautifulsoup4

Virtual Environments是一個隔離各個項目lib防止沖突的機制,由于我初學(xué),先不用

安裝完bs4之后試一下:

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read())
print(bsObj.h1)

直接使用bsObj.h1找到了html中的h1標(biāo)簽里的內(nèi)容。這是比較暴力的寫法,比較精確的寫法是bsObj.html.body.h1

異常處理

異常處理可以使程序更健壯,不容易直接掛掉??聪旅娴膶懛ǎ?/p>

from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup

def getTitle(url):
    try:
        html = urlopen(url)
    except HTTPError as e:
        return None
    try:
        bsObj = BeautifulSoup(html.read())
        title = bsObj.body.h1
    except AttributeError as e:
        return None
    return title
title = getTitle("http://www.pythonscraping.com/pages/page1.html")
if title == None:
    print("Title could not be found")
else:
    print(title)

以上方法才是比較正規(guī)健壯的寫法,一定要注意格式,不然會報錯的,不行就裝個IDE 比如Pycharm,如果格式不正確會有提示。

高級HTML解析

從一個復(fù)雜的頁面提取到需要的信息可能需要深層的抓取比如:
bsObj.findAll("table")[4].findAll("tr")[2].find("td").findAll("div")[1].find("a")
這樣的代碼很可怕也很脆弱,當(dāng)頁面出現(xiàn)改動后,這個路徑就抓不到信息了。
有什么解決方案?

  • 通過手機版或打印預(yù)覽,來獲取更規(guī)范的HTML
  • 解析網(wǎng)頁引用的js文件
  • 通過網(wǎng)頁URL獲取信息
  • 從其他類似的網(wǎng)站獲取信息

書上說的以上方法很濕,一點都不干貨...

BeautifulSoup 的其功能

使用屬性、導(dǎo)航樹、搜索標(biāo)簽
網(wǎng)頁的樣式表 也可以用來查找信息

看例子,這個網(wǎng)頁,有red和green的文字:
http://www.pythonscraping.com/pages/warandpeace.html
下面我們來爬一下,打印出所有綠色的文字:

from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://www.pythonscraping.com/pages/warandpeace.html")
bsObj = BeautifulSoup(html)
nameList = bsObj.findAll("span", {"class":"green"})
for name in nameList:
    print(name.get_text())

以上,使用bsObj.findAll(tagName, tagAttributes)查詢返回列表

find()和findAll()的用法

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

查找多個類型的標(biāo)題:

.findAll({"h1","h2","h3","h4","h5","h6"})

查找多個屬性:

.findAll("span", {"class":"green", "class":"red"})

遞歸

findAll()方法的遞歸屬性默認(rèn)是true,意味著查找所有子節(jié)點。

以內(nèi)容為條件查詢標(biāo)簽:

nameList = bsObj.findAll(text="the prince")
print(len(nameList))

limit

limit是限制查找的個數(shù),比如只返回前10個符合條件的標(biāo)簽

keywords

有點復(fù)雜 先不看

Navigation Trees

Navigation Tree就類似這種用法:
bsObj.tag.subTag.anotherSubTag

一個用來做例子的頁面:
http://www.pythonscraping.com/pages/page3.html

處理子節(jié)點和后代節(jié)點

在BeautifulSoup里面 子節(jié)點child和“”孫子及后代“descendants 是被兩個概念。兩個范圍沒有交集。
注意bsObj.body.h1這個代碼返回的不一定是 body-h1,而有可能是body-........h1。
如果只想得到兒子則使用:bsObj.find("table",{"id":"giftList"}).children這種方式。

處理sibling兄弟姐妹

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)

打印出了所有的產(chǎn)品內(nèi)容,出了第一行title。原因:

  • sibling(兄弟)不包括自己
  • next_siblings只返回next的,而不是它和它之前的,如果object本身在在隊列中間,那么只返回它后面的兄弟

同理如果需要返回前面的兄弟可以使用previous_siblings

以上兩周可以理解為,返回哥哥、返回弟弟
另外,去掉siblings后面的s 可以只返回一個靠的最近的兄弟。

處理爹媽,父標(biāo)簽(這標(biāo)題...)

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())
逆時針箭頭順序

正則表達(dá)

正則表達(dá)式....呃 頭大

As the old computer-science joke goes: “Let’s say you have a problem, and you decide
to solve it with regular expressions. Well, now you have two problems.”

爬蟲技術(shù)脫不了使用正則表達(dá)式

上面的例子使用的是準(zhǔn)確的src來找到特指的img,但是如果要找很多的img就要使用正則了:

from urllib.request import urlopen
from bs4 import BeautifulSoup
import 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"])

獲取屬性

myImgTag.attrs['src']

Lambda表達(dá)式

將一個方法作為變量傳遞到另一個方法中,但是方法的參數(shù)必須是一個tag返回一個boolean
例子:
soup.findAll(lambda tag: len(tag.attrs) == 2)
返回有兩個屬性的標(biāo)簽
這可能是替代正則表達(dá)式的一種方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容