python網絡數據採集筆記(一)

注意:html

1.爲了不一個頁面被採集兩次, 連接去重是很是重要的。
2.寫代碼以前擬個大綱或畫個流程圖是很好的編程習慣,這麼作不只能夠爲你後期處理節省
不少時間,更重要的是能夠防止本身在爬蟲變得愈來愈複雜時亂了分寸。
3.處理網頁重定向
正則表達式

  •服務器端重定向,網頁在加載以前先改變了 URL
  • 客戶端重定向,有時你會在網頁上看到「10 秒鐘後頁面自動跳轉到……」之類的消息,
  表示在跳轉到新 URL 以前網頁須要加載內容。
編程

  服務器端重定向,你一般不用擔憂。若是你在用 Python 3.x 版本的 urllib 庫,它會自
  動處理重定向。不過要注意,有時候你要採集的頁面的 URL 可能並非你當前所在頁
  面的 URL
服務器

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
import datetime
import random


pages = set()
#隨機數種子
random.seed(datetime.datetime.now())

#獲取頁面全部內鏈的列表
def getInternalLinks(bsObj, includeurl):
    internalLinks = []
    #匹配以/開頭的字符串,或匹配包括includeurl的字符串,+表示字符串拼接。
    for link in bsObj.find_all("a", href=re.compile("^(/|.*" +includeurl+")")):
    #for link in bsObj.find_all("a", href=re.compile("^(.*" + includeurl + ")")):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in internalLinks:
                internalLinks.append(link.attrs['href'])
    return internalLinks

#獲取頁面內全部外鏈的列表
def getExternalLinks(bsObj, excludeurl):
    externalLinks = []
    # 找出全部以"http""www"開頭且不包含當前URL的連接
    for link in bsObj.find_all("a", href=re.compile("^(http|www)((?!" +excludeurl+").)*$")):
        if link.attrs['href'] is not None:
            if link.attrs['href'] not in externalLinks:
                externalLinks.append(link.attrs['href'])
    return externalLinks

#URL連接切片,爲了得到域名
def splitAddress(adress):
    adressParts = adress.replace("http://", "").split("/")
    return adressParts

#於外鏈列表中隨機選取一條外鏈
def getRandomExternalLink(startingpage):
    html = urlopen(startingpage)
    bsObj = BeautifulSoup(html, "lxml")
    externalLinks = getExternalLinks(bsObj, startingpage)
    if len(externalLinks) == 0:
        internalLinks = getInternalLinks(startingpage)
        return getExternalLinks(internalLinks[random.randint(0, len(internalLinks)-1)])
    else:
        return externalLinks[random.randint(0, len(externalLinks)-1)]

#外鏈跳轉,從一條外鏈跳轉到另外一條
def followExternalOnly(siteurl):
    externalLink = getRandomExternalLink(siteurl)
    print("隨機外鏈:", externalLink)
    followExternalOnly(externalLink)

#收集網站內全部外鏈列表
allExtLinks = set()
allIntLinks = set()

def getAllExternalLinks(siteurl):
    html = urlopen(siteurl)
    bsObj = BeautifulSoup(html, "lxml")
    internalLinks = getInternalLinks(bsObj, splitAddress(siteurl)[0])
    externalLinks = getExternalLinks(bsObj, splitAddress(siteurl)[0])
    for link in externalLinks:
        if link not in allExtLinks:
            allExtLinks.add(link)
            print(link)
    for link in internalLinks:
        if link not in allIntLinks:
            allIntLinks.add(link)
            print("即將獲取連接的URL是:"+link)
            getAllExternalLinks(link)

#從互聯網採集,從一個外鏈跳轉到另外一個外鏈
#followExternalOnly("http://oreilly.com")
#獲取網站全部外鏈
getAllExternalLinks("http://oreilly.com")

說明:以上代碼能夠執行兩個功能。僅運行followExternalOnly("http://oreilly.com")是從互聯網採集,從一個外鏈跳轉到另外一個外鏈。app

  僅運行getAllExternalLinks("http://oreilly.com")能夠獲取網站全部外鏈。dom

說一下運行getAllExternalLinks("http://oreilly.com")遇到的問題,發生raise ValueError("unknown url type: %r" % self.full_url),ValueError: unknown url type: '/oscon/oscon-or/schedule'函數

是否是問題出如今獲取頁面全部內鏈函數getInternalLinks()的for link in bsObj.find_all("a", href=re.compile("^(/|.*" +includeurl+")")):的部分。爲什麼要匹配以/開頭的URL?網站

不懂,留待之後解決吧。。。但願我別忘了。。。ui

 

備註:
url

BeautifulSoup的find()find_all()

BeautifulSoup裏的find()find_all()多是你最經常使用的兩個函數。藉助它們,你能夠經過標籤的不一樣屬性輕鬆地過濾HTML頁面,查找須要的標籤組或單個標籤。

BeautifulSoup文檔地址:http://beautifulsoup.readthedocs.io

find()函數語法:

find( name , attrs , recursive , string , **kwargs ) 

find_all()函數語法:

find_all( name , attrs , recursive , string , **kwargs ) 

搜索當前tag的全部tag子節點,並判斷是否符合過濾器的條件。

name參數能夠查找全部名字爲name的tag,字符串對象會被自動忽略掉。搜索 name參數的值可使任一類型的過濾器,字符串,正則表達式,列表,方法等。

attrs參數定義一個字典參數來搜索包含特殊屬性的tag

經過string參數能夠搜搜文檔中的字符串內容,與name參數的可選值同樣。

keyword參數:若是一個指定名字的參數不是搜索內置的參數名,搜索時會把該參數看成指定名字tag的屬性來搜索。

find_all()方法返回所有的搜索結構,若是文檔樹很大那麼搜索會很慢。若是咱們不須要所有結果,可使用 limit參數限制返回結果的數量.效果與SQL中的limit關鍵字相似,當搜索到的結果數量達到limit的限制時,就中止搜索返回結果。

find 等價於 find_all 的 limit 等於 1 ;

調用tag的 find_all()方法時,Beautiful Soup會檢索當前tag的全部子孫節點,若是隻想搜索tag的直接子節點,可使用參數 recursive=False

其餘BeautifulSoup對象

NavigableString對象:表示標籤裏面的文字;
Comment對象:用來查找HTML文檔的註釋標籤。

相關文章
相關標籤/搜索