教材:《Web Scraping with Python——Collecting Data from the Modern Web》? 2015 by Ryan Mitchell
之所以叫網(wǎng)絡(luò)爬蟲(Web crawler)攻礼,是因?yàn)樗鼈兛梢匝刂W(wǎng)絡(luò)爬行。本質(zhì)就是一種遞歸方式仅淑。為了找到 URL 鏈接,爬蟲必須首先獲取網(wǎng)頁(yè)內(nèi)容丸冕,檢查這個(gè)頁(yè)面的內(nèi)容油额,再尋找另一個(gè) URL逞泄,然后獲取 URL 對(duì)應(yīng)的網(wǎng)頁(yè)內(nèi)容担租,不斷循環(huán)這一過程。
提取頁(yè)面鏈接:
from urllib.request import urlopen
from bs4 import BeautifulSoup
html = urlopen("http://en.wikipedia.org/wiki/Kevin_Bacon")
bsObj = BeautifulSoup(html)
for link in bsObj.findAll("a"):
? ? if 'href' in link.attrs:
? ? print(link.attrs['href'])
過濾多余的連接:
以僅提取“詞條鏈接”為例鲫构,相比于“其他鏈接”浓恶,“詞條鏈接”:
? 都在 id 是 bodyContent 的 div 標(biāo)簽里?
? URL 鏈接不包含分號(hào)
? URL 鏈接都以 /wiki/ 開頭
——利用find()方法和正則表達(dá)式過濾“其他鏈接”:
from urllib.request import urlopen
from bs4 import BeautifulSoup
import datetime
import random
import re
random.seed(datetime.datetime.now())
def getLinks(articleUrl):
? ? html = urlopen("http://en.wikipedia.org"+articleUrl)
? ? bsObj = BeautifulSoup(html, "html.parser")
? ? return bsObj.find("div", {"id":"bodyContent"}).findAll("a", href=re.compile("^(/wiki/)((?!:).)*$"))
links = getLinks("/wiki/Kevin_Bacon")
while len(links) > 0:
? ? newArticle = links[random.randint(0, len(links)-1)].attrs["href"]
? ? print(newArticle)
links = getLinks(newArticle)
鏈接去重:
為了避免一個(gè)頁(yè)面被采集兩次,鏈接去重是非常重要的结笨。在代碼運(yùn)行時(shí)包晰,把已發(fā)現(xiàn)的所有鏈接都放到一起,并保存在方便查詢的列表里(下文示例指 Python 的集合 set 類型)炕吸。只有“新”鏈接才會(huì)被采集伐憾,之后再?gòu)捻?yè)面中搜索其他鏈接:
遍歷首頁(yè)上每個(gè)鏈接,并檢查是否已經(jīng)在全局變量集合 pages 里面了(已經(jīng)采集的頁(yè)面集合)算途。如果不在塞耕,就打印到屏幕上,并把鏈接加入pages 集合嘴瓤,再用 getLinks 遞歸地處理這個(gè)鏈接。
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
pages = set()
def getLinks(pageUrl):
global pages
html = urlopen("http://en.wikipedia.org"+pageUrl)
bsObj = BeautifulSoup(html)
for link in bsObj.findAll("a", href=re.compile("^(/wiki/)")):
if 'href' in link.attrs:
if link.attrs['href'] not in pages:
# we meet the new page
newPage = link.attrs['href']
print(newPage)
pages.add(newPage)
getLinks(newPage)
getLinks("")
收集整個(gè)網(wǎng)站數(shù)據(jù)的組合程序:
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
pages = set()
def getLinks(pageUrl):
global pages
html = urlopen("http://en.wikipedia.org"+pageUrl)
bsObj = BeautifulSoup(html, "html.parser")
try:
print(bsObj.h1.get_text())
print(bsObj.find(id ="mw-content-text").findAll("p")[0])
print(bsObj.find(id="ca-edit").find("span").find("a").attrs['href'])
except AttributeError:
print("This page is missing something! No worries though!")
for link in bsObj.findAll("a", href=re.compile("^(/wiki/)")):
if 'href' in link.attrs:
if link.attrs['href'] not in pages:
#We have encountered a new page
newPage = link.attrs['href']
print("----------------\n"+newPage)
pages.add(newPage)
getLinks(newPage)
getLinks("")