Python爬蟲-獲得某一連結下的所有超連結

ywsdxxzj發表於2020-11-08

Python爬蟲-獲得某一連結下的所有超連結

用到的庫

Beautifulsoup4、requests、re模組

import requests as rq
from bs4 import BeautifulSoup as bs
import re

具體實現:

1. 獲得某頁面的html內容

要獲得某一個頁面的html,沒什麼好說,直接呼叫request庫吧!

要注意的是這裡request.get()返回的是一個response型別,但是這個類其實是包括了我們需要的html資訊的,只需要呼叫該類的text()方法即可返回網頁的原始碼。

def gethtml(rooturl, encoding="utf-8"):
    # 預設解碼方式utf-8
    response = rq.get(rooturl)
    response.encoding = encoding
    html = response.text
    return html  # 返回連結的html內容

3.獲得某html下的所有超連結

現在我們獲得了某一個網址的原始碼,學過html或者資料結構的同學都很容易知道,我們要找的超連結一般是藏在DOM樹的a節點下的。

這是樹結構邏輯上的示意圖:
圖片來自:https://www.w3school.com.cn/htmldom/dom_nodes.asp
在實際的html檔案中,即為如下所示的地方(節點):
在這裡插入圖片描述
現在我們知道了超連結在html中所處的位置,可是該如何獲取他們呢?一種方法是使用正規表示式把html當成字串暴力處理,思路上就是類似if “<a + 別的啥字元>” in html的模式;另外一種是我們可以呼叫BeautifulSoup庫強大的解析功能,讓他幫我們定位,不過這樣我們還需遵循如下的語法細節:

  1. BeautifulSoup()函式返回的是一個解析過的物件,相當於把你的html文字做了處理;
  2. 呼叫這個解析過的物件的find_all()方法,即返回一個該html中 所有的a節點組成的列表;
  3. 再對錶中每一個節點呼叫get()方法,獲得該節點下"herf"標籤(鍵)的所有值,也就是我們的要找“http://”打頭的超連結了;
def getherf(html):
    # 使用BeautifulSoup函式解析傳入的html
    soup = bs(html, features="lxml")
    allnode_of_a = soup.find_all("a")
    result = [_.get("href") for _ in allnode_of_a]
    # print(result)
    return result

4.篩除結果中非連結的元素

實際應用過程中我們會發現,有些herf的值並不是我們要找的超連結,而是其他的文字:
在這裡插入圖片描述
這就導致獲取到的result中還包含一些奇怪的東西:
在這裡插入圖片描述

如此,我們就需要對獲得的結果進行一次篩查,排除不需要的元素並保留連結,那這裡比較直接的方法就是使用前面提到的正則化,簡單來說,"http://"打頭的就留下,否則就刪除:

  • re.match(pattern, string)可以接收兩個引數,前者是模式後者是待匹配字元,形象地理解為:通過re.match(長得高,一堆女的)來找我的理想型女朋友,那得先有要求才能相親啊
  • urlptn即匹配模式,單獨的“.”表示除\n外的所有單字元,(.+)就表示http://後面的單字元重複1次或多次;
  • 但是re.macth()返回的並不直接是我們需要的連結,倘若匹配成功,我們需要對獲得的物件(長得高的更可能成為物件 (大霧))呼叫group()方法來獲得字串,即為連結;
  • 這麼做的問題是:若匹配失敗,返回的none也在表中了,但是none沒有group方法,程式就會報錯,那我們只需要在逐個呼叫group前篩除所有none就好了,我這裡採用的是while迴圈的辦法。
def filterurl(result):
    # result引數:get到的所有a標籤內herf的內容
    # 對列表中每個元素進行篩選
    urlptn = r"http://(.+)"  # 匹配模式: 所有http://開頭的連結
    urls = [re.match(urlptn, str(_)) for _ in result]  # 正則篩選
    # print(urls)
    while None in urls:
        urls.remove(None)  # 移除表中空元素
    urls = [_.group() for _ in urls]  # group方法獲得re.match()返回值中的字元
    # print(urls)
    return urls

主程式

html = gethtml("http://huxi.cqu.edu.cn/")
result = getherf(html)
urls = filterurl(result)
print(urls)

大功告成!

在這裡插入圖片描述
這樣一來我們就完成了對某一網址的所有超連結的提取,後續再順藤摸瓜來爬取被指向的網站就容易很多了。當然對某一網站的其他內容(圖片,音訊,電子書等)的提取也大同小異,例如有的網站的圖片連結是儲存在img節點下的,即img節點的src鍵對應的值,那我們只需要簡單修改定位的函式即可。

相關文章