小說爬蟲——以https://www.tadu.com/book/catalogue/891710/(小說目錄)為例
阿新 • • 發佈:2022-03-25
-
-
目標內容:小說《沒有爸爸也能活》第一章到第十三一章的正文內容。
-
任務要求:編寫兩個爬蟲,爬蟲1從https://www.tadu.com/book/catalogue/891710/
def get_source(self, url, headers):#獲取url原始碼 return requests.get(url, headers).content.decode()
def url2redis(self):#將url原始碼中的章節url儲存在redis資料庫中
source = self.get_source(self.url,self.HEADERS)
selector = lxml.html.fromstring(source) # 建立樹物件
url_lst = selector.xpath('//div[@class="chapter clearfix"]/a/@href')
for url in url_lst:
url = 'https://www.tadu.com' + url.strip()
self.client1.lpush('url_queue', url)
2.其次從url_queue中一個個彈出章節url,由於章節內容採取非同步載入的方式,剛開始使用了selenium,通過webdriver來驅動Chrome瀏覽器,來解析JS接收資料,獲取元素原始碼。
def wait(url):#用於獲取 driver = webdriver.Chrome(r'.\chromedriver.exe')#用chromedriver.exe驅動Chrome瀏覽器解析原始碼中JS部分 driver.get(url) #連線網頁 try: WebDriverWait(driver,30).until(EC.presence_of_element_located((By.CLASS_NAME,"read_details"))) #等待頁面載入 except Exception as _: print('網頁載入太慢。') return driver.page_source #返回網頁原始碼
3.最後把這些章節內容原始碼,通過Xpath來獲取小說標題和內容,將其加入字典列表裡,用於插入MongoDB資料庫
def article2mongodb(self):#將各個url中文章內容傳入MongoDB資料庫中 while self.client1.llen('url_queue')>0: url = self.client1.lpop('url_queue').decode() html = wait(url) selector = lxml.html.fromstring(html) chapter_name = selector.xpath('//div[@class="clearfix"]/h4/text()')[0] content = selector.xpath('//div[@id="partContent"]/p/text()') self.content_lst.append({'title':chapter_name,'content':content}) self.handler.insert_many(self.content_lst)
5.原始碼:
# Author:CK # -*- coding = utf-8 -*- # @Time :2022/3/24 17:21 # @Author:ck # @File :get_article.py # @Software: PyCharm from selenium import webdriver#瀏覽器驅動模組 from selenium.webdriver.support.ui import WebDriverWait#瀏覽器請求等待模組 from selenium.webdriver.common.by import By#鎖定元素模組 from selenium.webdriver.support import expected_conditions as EC#期待模組 import requests#請求模組 import lxml.html#原始碼解析模組 import redis #redis資料庫 from pymongo import MongoClient #MongoDB資料庫 def wait(url):#用於獲取 driver = webdriver.Chrome(r'.\chromedriver.exe')#用chromedriver.exe驅動Chrome瀏覽器解析原始碼中JS部分 driver.get(url) #連線網頁 try: WebDriverWait(driver,30).until(EC.presence_of_element_located((By.CLASS_NAME,"read_details"))) #等待頁面載入 except Exception as _: print('網頁載入太慢。') return driver.page_source #返回網頁原始碼 class get_article(object):#獲取文章內容類 HEADERS = { 'User - Agent': 'Mozilla / 5.0(WindowsNT10.0;WOW64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 99.0.4844.51Safari / 537.36' }#頭部 def __init__(self, url): self.url = url self.content_lst = [] self.client1 = redis.StrictRedis()#連線redis資料庫 self.handler = db['article']#連線資料庫集合 self.url2redis() self.article2mongodb() def get_source(self, url, headers):#獲取url原始碼 return requests.get(url, headers).content.decode() def url2redis(self):#將url原始碼中的章節url儲存在redis資料庫中 source = self.get_source(self.url,self.HEADERS) selector = lxml.html.fromstring(source) # 建立樹物件 url_lst = selector.xpath('//div[@class="chapter clearfix"]/a/@href') for url in url_lst: url = 'https://www.tadu.com' + url.strip() self.client1.lpush('url_queue', url) def article2mongodb(self):#將各個url中文章內容傳入MongoDB資料庫中 while self.client1.llen('url_queue')>0: url = self.client1.lpop('url_queue').decode() html = wait(url) selector = lxml.html.fromstring(html) chapter_name = selector.xpath('//div[@class="clearfix"]/h4/text()')[0] content = selector.xpath('//div[@id="partContent"]/p/text()') self.content_lst.append({'title':chapter_name,'content':content}) self.handler.insert_many(self.content_lst) if __name__ =='__main__': client0 =MongoClient() db = client0['spicer']#建立資料庫 article = get_article('https://www.tadu.com/book/catalogue/891710')
6.但實際執行,由於每次爬取一個章節內容都會執行一次Chrome解析器,所耗用記憶體過大,要想解決這個問題,得想個其它思路。由於非同步載入,我們可以在瀏覽器開發者工具中找到每個章節的資料檔案。通過對每個資料檔案內容、url、請求方式的解析,從而只需要簡單爬蟲模式即可爬取。思路僅供參考,具體原始碼實現自考。