二手房在哪個(gè)網(wǎng)站做合同互聯(lián)網(wǎng)營銷師培訓(xùn)大綱
1.需求背景
爬取松產(chǎn)品中心網(wǎng)站下的家電說明書。這里以冰箱為例:松下電器-冰箱網(wǎng)址
網(wǎng)站分析:
第一步:
點(diǎn)擊一個(gè)具體的冰箱型號(hào),點(diǎn)擊了解更多,會(huì)打開此型號(hào)電器的詳情頁面。
第二步:在新打開的詳情頁面中說明書下載標(biāo)識(shí)
第三步:點(diǎn)擊說明書下載,將下載此說明書
2.實(shí)現(xiàn)思路與核心步驟
由以上操作,我們知道了模擬用戶點(diǎn)擊的具體步驟,大致得到了一個(gè)整體思路。
主要難點(diǎn):
- 如何在整個(gè)頁面中定位到某一個(gè)具體的電器型號(hào),如何遍歷依次得到此頁面所有型號(hào)
- 打開新頁面,如何切換到新打開的窗口
- 如何定位到新打開窗口的說明書下載按鈕
- 下載完成后如何切換回到原始的頁面,進(jìn)行下一個(gè)電器的點(diǎn)擊
- 多個(gè)頁面,如何進(jìn)行翻頁
2.1 得到新頁面的鏈接
依次解決:
1.按F12,打開開發(fā)者模式,點(diǎn)擊如圖所示的1,檢查,點(diǎn)擊了解詳情2,會(huì)自動(dòng)定位顯示如圖3所示。
發(fā)現(xiàn)3標(biāo)識(shí)的href就是此型號(hào)的詳情頁面。所以可以編寫函數(shù)得到此鏈接。
這里也有兩種方式:
方式一:使用Selenium模擬用戶點(diǎn)擊,使用xpath定位得到此href
方式二:使用requests直接得到此頁面中的所有href鏈接,發(fā)現(xiàn)具體型號(hào)的鏈接時(shí)帶有product,依據(jù)此進(jìn)行篩選。
本文使用方式二:
def get_allurl(url):'''得到url下,所有以.html結(jié)尾的href標(biāo)簽下的鏈接:param url::return:'''result_link = []html_content = requests.get(url).textsoup = BeautifulSoup(html_content, "html.parser")# 由開發(fā)者模式下可以看出,我們需要的href標(biāo)簽時(shí)a,且時(shí)以.html為結(jié)尾link_nodes = soup.find_all('a', href=lambda href: href and href.endswith('.html'))for node in link_nodes:tem_url=node.get("href")result_link.append(tem_url)return result_link
2.2 模擬用戶進(jìn)行點(diǎn)擊下載
進(jìn)入此頁面,發(fā)現(xiàn)此網(wǎng)站下的鏈接并不是直接以.pdf為結(jié)尾的鏈接,而是有封裝了一層,所以只能通過模擬用戶點(diǎn)擊的方式。
同時(shí)需要點(diǎn)擊兩次,首先第一次時(shí)說明書下載,出來具體型號(hào),我們這里只選第一個(gè)NR-ZE391LG-W這個(gè)位置。
點(diǎn)擊這些位置,得到其對(duì)應(yīng)的XPATH
代碼實(shí)現(xiàn)如下:
def clik_url(url):# 初始化WebDriverdriver = webdriver.Chrome()# 導(dǎo)航到包含鏈接的網(wǎng)頁driver.get(url)# 為了防止有的型號(hào)不包含說明書,不存在對(duì)應(yīng)的xpath路徑,出現(xiàn)錯(cuò)誤,終止程序# 這里使用了try excepttry:# 找到說明書下載按鈕的Xpath ='/html/body/div[5]/div/div[2]/div[1]/div/div[1]'click_element = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, '/html/body/div[5]/div/div[2]/div[1]/div/div[1]')))# 點(diǎn)擊說明書下載click_element.click()# 頁面加載完成后會(huì)出現(xiàn)具體型號(hào),比如圖中的NR-ZE391LG-W,找到此位置res=WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, '/html/body/div[5]/div/div[2]/div[1]/div/div[2]/ul/li/a')))# 此位置包含了一個(gè)以.pdf為結(jié)尾的href鏈接,是我們需要找的。if res:new_url=res.get_attribute('href')# get_pdf(new_url)print(new_url)time.sleep(2)driver.quit()return new_urlelse:print("none")time.sleep(2)driver.quit()return Noneexcept:time.sleep(2)driver.quit()pass
此函數(shù)返回了pdf的具體鏈接,由此鏈接就可以直接獲取到pdf文件
2.3 獲取pdf文件
由以上得到的pdf鏈接,獲取保存為pdf文件。例如:
https://home.panasonic.cn/support/attachments/auld/manual/NR-ZE391LG-W.pdf
def get_pdf(url,output_dir):'''url是一個(gè)后綴為.pdf的鏈接,點(diǎn)擊就可以下載pdf文件,此函數(shù)保存pdf到output_dir路徑:param url::param output_dir::return:'''if not os.path.exists(output_dir):os.makedirs(output_dir)# 下載文件try:response = requests.get(url, stream=True)response.raise_for_status()except:return# 提取文件名(這里需要根據(jù)你的URL結(jié)構(gòu)或鏈接的href屬性來提取)# 假設(shè)文件名是URL的最后一部分(不包括查詢參數(shù))filename = os.path.basename(urlparse(url).path)# 將文件保存到本地with open(os.path.join(output_dir, filename), 'wb') as f:for chunk in response.iter_content(1024):f.write(chunk)print(f'Downloaded: {filename}')
3. 整體流程和代碼實(shí)現(xiàn)
def get_allurl(url):······如上所示······return result_linkdef get_pdf(url,output_dir):······如上所示······def clik_url(url):······如上所示······return new_url# 函數(shù)開始入口
def page_res(page_url,output_dir):# 1.點(diǎn)擊到電飯煲的主頁面,返回這個(gè)頁面下所有的以.html結(jié)尾的網(wǎng)址prod_urls = get_allurl(page_url)# 2.遍歷網(wǎng)址,進(jìn)行pdf下載for i in range(len(prod_urls)):print(prod_urls[i])# 有一些.html的網(wǎng)頁也不含pdf,發(fā)現(xiàn)含的都帶有product字樣,所以進(jìn)行過濾if 'product' in str(prod_urls[i]):# 3.點(diǎn)擊得到新出現(xiàn)的pdf鏈接pdf_url = clik_url(prod_urls[i])if pdf_url:# 4.進(jìn)行pdf文件下載get_pdf(pdf_url, output_dir)print("本頁下載已完成")
如果想要獲取更多頁面的冰箱型號(hào),可以觀察到不同頁面的url是由規(guī)律的,直接for循環(huán)遍歷頁面就行了。
4.總結(jié)
1.使用獲取所有鏈接再進(jìn)行篩選的方式,代替了模擬用戶點(diǎn)擊以此定位具體位置,進(jìn)行點(diǎn)擊
2.在新打開的頁面中沒有直接暴露pdf鏈接,需要點(diǎn)擊說明書下載按鈕才能得到pdf鏈接,點(diǎn)擊一次,顯示pdf鏈接之后,并沒有繼續(xù)采用用戶點(diǎn)擊的方式,而是直接獲取(這與網(wǎng)站有關(guān),有點(diǎn)還是不會(huì)顯示出來,只有點(diǎn)擊才會(huì)出現(xiàn))
因?yàn)闆]用采用點(diǎn)擊,也不存在頁面切換的問題。相比于全部Selenium模擬用戶點(diǎn)擊,少了許多步驟。