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()
背景:
高數老師竟然不提前發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])
使用方法及成品展示
我們先要設置源碼里的username和password,注意是超星課堂的,一般username是手機號
然后設置你要保存ppt的路徑,源碼里是d盤ppt里的高數ppt,可以自己改
我們只要將有章節列表的頁面的網址完全復制下來,然后運行我們的python程序,按照提示粘貼剛剛復制的鏈接就可以啦