1. 程式人生 > 其它 >爬蟲入門之爬取網頁ppt成品及製作思路隨筆

爬蟲入門之爬取網頁ppt成品及製作思路隨筆

python爬蟲入門實現爬取ppt隨筆

先上原始碼!

from selenium import webdriver
import requests
from selenium.webdriver.common.by import By
import os,fitz,pprint
username = ''
password = ''
fpath = 'D:/ppt/高數ppt'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}
baseurl = input('輸入連結:')
driver = webdriver.Firefox()
driver.implicitly_wait(10)
driver.get(baseurl)
un = driver.find_element(By.CSS_SELECTOR,'#phone')
pwd = driver.find_element(By.CSS_SELECTOR,'#pwd')
lgin = driver.find_element(By.CSS_SELECTOR,'#loginBtn')
un.send_keys(username)
pwd.send_keys(password)
lgin.click()
def eachurl(locurl):
	driver.execute_script('window.open("'+locurl+'")')
	handles = driver.window_handles
	driver.switch_to.window(handles[-1])
	fname = driver.find_element(By.CSS_SELECTOR, '#mainid h1').text + '.pdf'
	driver.switch_to.frame('iframe')
	try:
		frame = driver.find_element(By.TAG_NAME, 'iframe')
		driver.switch_to.frame(frame)
	except:
		pass
	try:
		driver.switch_to.frame('panView')
	except:
		pass
	elems = driver.find_elements(By.CSS_SELECTOR, 'img[src*="http"]')
	urls = []
	for elem in elems:
		urls.append(elem.get_attribute('src'))
	pprint.pprint(urls)
	if len(urls)==0:
		return
	os.makedirs(fpath, exist_ok=1)
	os.chdir(fpath)
	doc = fitz.open()
	for i in range(len(urls)):
		r = requests.get(urls[i], headers=headers)
		with open(str('tmp') + '.png', 'wb') as f:
			f.write(r.content)
		imgdoc = fitz.open(f)
		pdfbytes = imgdoc.convert_to_pdf()
		pdf_name = str(i) + '.pdf'
		imgpdf = fitz.open(pdf_name, pdfbytes)
		doc.insert_pdf(imgpdf)
	doc.save(fname)
	os.remove(str('tmp') + '.png')
	doc.close()
	driver.close()
	urls.clear()
locelems = driver.find_elements(By.CSS_SELECTOR,'.leveltwo .clearfix a')
def operateurls(locelems):
	for locelem in locelems:
		newurl = locelem.get_attribute('href')
		print(newurl)
		eachurl(newurl)
		handles = driver.window_handles
		driver.switch_to.window(handles[0])
operateurls(locelems)
eachurl(baseurl)
driver.quit()

使用方法及成品展示

我們先要設定原始碼裡的username和password,注意是超星課堂的,一般username是手機號

然後設定你要儲存ppt的路徑,原始碼裡是d盤ppt裡的高數ppt,可以自己改

我們只要將有章節列表的頁面的網址完全複製下來,然後執行我們的python程式,按照提示貼上剛剛複製的連結就可以啦

背景:

高數老師竟然不提前發ppt在qq群裡!然而不預習聽高數真的是一種煎熬,所以經過百般搜尋,在我們學校的資源平臺上找到了高數ppt的資源。BUT!

如圖所示,這個ppt被放在一個iframe框架裡,並且沒有下載的入口,而我並不想每次看ppt都要開啟網頁!於是我用瀏覽器自帶的開發工具檢查頁面原始碼,發現他放的都是ppt內容的png格式檔案!

不過經過萬能的bing搜尋,發現python有fitz庫,可以將png圖片轉化為pdf格式,這太方便啦!

所以理論上我們可以通過簡單的爬蟲來實現爬ppt這個功能,理論可行,實踐開始!

爬取單個頁面實現思路

匯入如下模組:

from selenium import webdriver#自動化操縱瀏覽器 
from selenium.webdriver.common.by import By#路徑選擇器會用到
import requests#用於下載圖片
import os#用於設定檔案存放路徑
import fitz#將png轉化為pdf
import pprint#為了打印出來漂亮,輸出哪些url被下載了

我們先得設定一下headers,避免網站把我們當作自動化機器人

headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}

我們現在建立一個webdriver物件,我這裡用的是火狐

#例項化出來webdriver物件
driver = webdriver.Firefox()
#設定最大等待時間,就是要是瀏覽器沒反應最多10s就停止了
driver.implicitly_wait(10)
#進入url
driver.get(baseurl)

我們首先需要用webdriver進入該節ppt的網頁檢視連結,但是我們用自動化方式操作瀏覽器時先要進行登入,介面如下:

我們用find_element方法找到輸入口和登入按鈕,並且將設定好的使用者名稱和密碼用send_keys方法輸進去,並且用click模擬點選登入按鈕


un = driver.find_element(By.CSS_SELECTOR,'#phone')
pwd = driver.find_element(By.CSS_SELECTOR,'#pwd')
lgin = driver.find_element(By.CSS_SELECTOR,'#loginBtn')

un.send_keys(username)
pwd.send_keys(password)
lgin.click()

現在我們就進入了有該節ppt的網站了

由於ppt在iframe框架中,且經過檢查有的不止一層,最多兩層,所以用try-except結構來進入ppt所在的最裡層

driver.switch_to.frame('iframe')
	try:
		frame = driver.find_element(By.TAG_NAME, 'iframe')
		driver.switch_to.frame(frame)
	except:
		pass
	try:
		driver.switch_to.frame('panView')
	except:
		pass

再找到存放png的所有網址存起來,並將含有連結的標籤存起來,再用get_attribute方法獲取src裡的連結放進url中

elems = driver.find_elements(By.CSS_SELECTOR, 'img[src*="http"]')
urls = []
	for elem in elems:
		urls.append(elem.get_attribute('src'))

用fitz庫轉換png並且把轉換的同一節pdf連一塊,檔案取名從網頁的標題裡可以找到

fname = driver.find_element(By.CSS_SELECTOR, '#mainid h1').text + '.pdf'
#fpath是儲存pdf的路徑是自己設定的
os.makedirs(fpath, exist_ok=1)
	os.chdir(fpath)
	doc = fitz.open()
	for i in range(len(urls)):
        #用request方法獲取url,再用二進位制的方式將url裡的圖片內容寫入臨時檔案
		r = requests.get(urls[i], headers=headers)
		with open(str('tmp') + '.png', 'wb') as f:
			f.write(r.content)
		imgdoc = fitz.open(f)
		#轉成pdf
		pdfbytes = imgdoc.convert_to_pdf()
		pdf_name = str(i) + '.pdf'
		imgpdf = fitz.open(pdf_name, pdfbytes)
        #插入pdf
		doc.insert_pdf(imgpdf)
	doc.save(fname)
    #將進行中轉的臨時檔案刪除
	os.remove(str('tmp') + '.png')
	doc.close()
    #再關閉當前頁面
    driver。close()

爬取多個頁面思路

我們發現高數的ppt在一個資源列表裡,

經過檢查瀏覽器元素,找到了列表的元素裡的href連結

於是我們就可以將單個頁面的思路進行擴充,即每次爬完列表中的一個連結,用seenium中操作視窗的手柄window_handles的switch_to.window()返回上一個視窗,繼續進入列表的下一個連結,呼叫爬取單個頁面的函式eachurl()爬取下一節課的ppt

#找到該頁面列表中所有的url,再通過爬取單個頁面的方式處理每個列表中的url
locelems = driver.find_elements(By.CSS_SELECTOR,'.leveltwo .clearfix a')
def operateurls(locelems):
	for locelem in locelems:
		newurl = locelem.get_attribute('href')
		print(newurl)
		eachurl(newurl)
		handles = driver.window_handles
		driver.switch_to.window(handles[0])