在本篇文章里,你將會學習把這些基本方法融合到一個更靈活的網站 爬蟲中,該爬蟲可以跟蹤任意遵循特定 URL 模式的鏈接。
這種爬蟲非常適用于從一個網站抓取所有數據的項目,而不適用于從特 定搜索結果或頁面列表抓取數據的項目。它還非常適用于網站頁面組織 得很糟糕或者非常分散的情況。
這些類型的爬蟲并不需要像上一節通過搜索頁面進行抓取中采用的定位 鏈接的結構化方法,因此在 Website 對象中不需要包含描述搜索頁面 的屬性。但是由于爬蟲并不知道待尋找的鏈接的位置,所以你需要一些 規則來告訴它選擇哪種頁面。你可以用 targetPattern(目標 URL 的 正則表達式)和布爾變量 absoluteUrl 來達成這一目標:
class Website: def __init__(self, name, url, targetPattern, absoluteUrl, titleTag, bodyTag): self.name = name self.url = url self.targetPattern = targetPattern self.absoluteUrl=absoluteUrl self.titleTag = titleTag self.bodyTag = bodyTagclass Content: def __init__(self, url, title, body): self.url = url self.title = title self.body = bodydef print(self): print("URL: {}".format(self.url)) print("TITLE: {}".format(self.title)) print("BODY:/n{}".format(self.body))
Content 類和第一個爬蟲例子中使用的是一樣的。
Crawler 類從每個網站的主頁開始,定位內鏈,并解析在每個內鏈頁面 發現的內容:
import reclass Crawler: def __init__(self, site): self.site = site self.visited = []def getPage(self, url): try:req = requests.get(url) except requests.exceptions.RequestException: return Nonereturn BeautifulSoup(req.text, 'html.parser')def safeGet(self, pageObj, selector):selectedElems = pageObj.select(selector)if selectedElems is not None and len(selectedElems) > 0:return '/n'.join([elem.get_text() forelem in selectedElems])return ''def parse(self, url):bs = self.getPage(url)if bs is not None:title = self.safeGet(bs, self.site.titleTag)body = self.safeGet(bs, self.site.bodyTag)if title != '' and body != '':content = Content(url, title, body)content.print()def crawl(self):"""獲取網站主頁的頁面鏈接"""bs = self.getPage(self.site.url)targetPages = bs.findAll('a',href=re.compile(self.site.targetPattern))for targetPage in targetPages:targetPage = targetPage.attrs['href']if targetPage not in self.visited:self.visited.append(targetPage)if not self.site.absoluteUrl:targetPage = '{}{}'.format(self.site.url, targetPage)self.parse(targetPage)reuters = Website('Reuters', 'https://www.reuters.com', '^(/article/)', False,'h1', 'div.StandardArticleBody_body_1gnLA') crawler = Crawler(reuters) crawler.crawl()
與前面的例子相比,這里的另外一個變化是:Website 對象(在這個例 子中是變量 reuters)是 Crawler 對象本身的一個屬性。這樣做的作 用是將已訪問過的頁面存儲在爬蟲中,但是也意味著必須針對每個網站 實例化一個新的爬蟲,而不是重用一個爬蟲去抓取網站列表。
新聞熱點
疑難解答