在完成基礎的表單畫面後,接著需要將之前完成的爬蟲功能整合至網站。
考量功能的獨立性、擴充性和使用便利性,這次預計將爬蟲功能打包成一個套件,今天的實作內容則為套件開發。
bookcrawler.py:提供使用者建立爬蟲物件。
plugin:放置plugin的資料夾。
宣告BookCrawler類別,作為使用者可以建立的物件。
init(self, url): 建立物件時需由使用者輸入URL,物件初始化流程包含:
屬性的初始化
URL大小寫轉換,確保資料品質
URL解析,取得網域
根據網域選擇合適的plugin
getinfo():任務為執行對應plugin中的實際的getinfo(),並將plugin中取得的網站資訊寫進主體。
import re
from crawler.plugin.wwwjjwxc_bookcrawler import wwwjjwxc_BookCrawler
class BookCrawler:
def __init__(self, url):
self.authorname = None
self.title = None
self.totalsection = 0
self.url = url.lower()
regex = r'(https?:\/\/)([\da-z\.-]+\.[a-z\.]{2,6})([\/\w \.-]*)*\/'
self.domain = re.search(regex, self.url).group(2)
# 依網域選擇plugin
### 暫時先hardcode ###
if self.domain == 'www.jjwxc.net':
self.plugin = wwwjjwxc_BookCrawler(self.url)
else:
self.plugin = None
#####################
# 若找不到插件,設定valid = False,表示此網站不支援
if self.plugin is None:
self.valid = False
else:
self.valid = True
def getinfo(self):
self.plugin.getinfo()
self.authorname = self.plugin.authorname
self.title = self.plugin.title
self.totalsection = self.plugin.totalsection
因各網站的HTML格式皆不相同,對應不同網域需要使用不同的plugin實作。
為了方便管理,便將各網站的plugin皆放置於此資料夾。
宣告抽象類別,定義plugin類別應有的屬性與方法。
未來開發的每支plugin程式都應繼承此抽象類別,由此來控管plugin屬性和方法的一致性。
class AbstractBookCrawler:
def __init__(self, url):
self.authorname = None
self.title = None
self.url = url
self.totalsection = 0
def getinfo():
pass
此程式實作了www.jjwxc.net的方法。
init(self, url):主要繼承母類別的初始化。為了處理HTML亂碼問題,另外定義了encoding屬性使用。
getinfo():爬蟲程式的本體。
import requests
import re
from bs4 import BeautifulSoup
from crawler.plugin.abstractclass import AbstractBookCrawler
class wwwjjwxc_BookCrawler(AbstractBookCrawler):
def __init__(self, url):
super().__init__(url)
self.encoding = 'gb18030'
def getinfo(self):
page = requests.get(self.url)
page.encoding = self.encoding
soup = BeautifulSoup(page.content, 'html.parser')
title_tag = soup.find("span",itemprop="articleSection")
author_tag = soup.find("span", itemprop="author")
totalsection_tag = soup.find_all("tr", itemprop=["chapter","chapter newestChapter"])
self.title = re.compile(r'>(.*)<').search(str(title_tag)).group(1)
self.authorname = re.compile(r'>(.*)<').search(str(author_tag)).group(1)
self.totalsection = totalsection_tag.__len__()