การขูดเว็บถูกใช้เพื่อดึงข้อมูลจากเว็บไซต์เกือบตั้งแต่ช่วงที่เวิลด์ไวด์เว็บถือกำเนิดขึ้น ในยุคแรกการขูดส่วนใหญ่จะทำบนหน้าเว็บแบบคงที่ซึ่งมีองค์ประกอบแท็กและข้อมูลที่รู้จัก
อย่างไรก็ตามเมื่อไม่นานมานี้เทคโนโลยีขั้นสูงในการพัฒนาเว็บทำให้งานยากขึ้นเล็กน้อย ในบทความนี้เราจะสำรวจวิธีการขูดข้อมูลในกรณีที่เทคโนโลยีใหม่และปัจจัยอื่น ๆ ป้องกันการขูดมาตรฐาน
เนื่องจากเว็บไซต์ส่วนใหญ่สร้างหน้าขึ้นสำหรับความสามารถในการอ่านของมนุษย์มากกว่าการอ่านแบบอัตโนมัติการคัดลอกเว็บส่วนใหญ่ประกอบด้วยการย่อยข้อมูลมาร์กอัปของหน้าเว็บโดยใช้โปรแกรม (คิดว่าคลิกขวาดูซอร์ส) จากนั้นตรวจจับรูปแบบคงที่ในข้อมูลนั้นซึ่งจะทำให้โปรแกรมได้ เพื่อ 'อ่าน' ข้อมูลต่างๆและบันทึกลงในไฟล์หรือฐานข้อมูล
หากพบข้อมูลรายงานบ่อยครั้งข้อมูลจะสามารถเข้าถึงได้โดยส่งผ่านตัวแปรรูปแบบหรือพารามิเตอร์ด้วย URL ตัวอย่างเช่น:
https://www.myreportdata.com?month=12&year=2004&clientid=24823
Python กลายเป็นหนึ่งในภาษาขูดเว็บที่ได้รับความนิยมมากที่สุดเนื่องจากเป็นส่วนหนึ่งของไลบรารีเว็บต่างๆที่สร้างขึ้น ห้องสมุดยอดนิยมแห่งหนึ่ง ซุปที่สวยงาม ออกแบบมาเพื่อดึงข้อมูลออกจากไฟล์ HTML และ XML โดยอนุญาตให้ค้นหานำทางและแก้ไขแท็ก (เช่นโครงสร้างการแยกวิเคราะห์)
เมื่อเร็ว ๆ นี้ฉันมีโครงการขูดที่ดูเหมือนจะตรงไปตรงมาและฉันก็พร้อมที่จะใช้การขูดแบบดั้งเดิมเพื่อจัดการกับมัน แต่เมื่อได้ศึกษาเพิ่มเติมก็พบอุปสรรคที่ไม่สามารถเอาชนะได้ด้วยวิธีการแบบเดิม ๆ
ปัญหาหลักสามประการที่ทำให้ฉันไม่สามารถใช้วิธีขูดมาตรฐานได้:
ดังนั้นฉันจึงตัดสินใจละทิ้งวิธีการแบบเดิมและดูเครื่องมือที่เป็นไปได้สำหรับการขูดบนเบราว์เซอร์ สิ่งนี้จะทำงานแตกต่างจากปกติ - แทนที่จะไปที่หน้าโดยตรงดาวน์โหลดแผนผังการแยกวิเคราะห์และดึงองค์ประกอบข้อมูลออกมาฉันจะ 'ทำตัวเหมือนมนุษย์' แทนและใช้เบราว์เซอร์เพื่อไปยังหน้าที่ฉันต้องการจากนั้นขูด ข้อมูล - ดังนั้นการหลีกเลี่ยงความจำเป็นในการจัดการกับอุปสรรคที่กล่าวถึง
โดยทั่วไปแล้ว ซีลีเนียม เป็นที่รู้จักกันดีในฐานะเฟรมเวิร์กการทดสอบโอเพ่นซอร์สสำหรับเว็บแอปพลิเคชัน - การเปิดใช้งาน ผู้เชี่ยวชาญด้าน QA เพื่อทำการทดสอบอัตโนมัติดำเนินการเล่นและใช้ฟังก์ชันการควบคุมระยะไกล (อนุญาตให้มีอินสแตนซ์เบราว์เซอร์จำนวนมากสำหรับการทดสอบโหลดและเบราว์เซอร์หลายประเภท) ในกรณีของฉันสิ่งนี้ดูเหมือนจะมีประโยชน์
ภาษา go-to ของฉันสำหรับการขูดเว็บคือ Python เนื่องจากมีไลบรารีที่รวมเข้าด้วยกันซึ่งโดยทั่วไปสามารถจัดการฟังก์ชันทั้งหมดที่จำเป็นได้ และนั่นเองค่ะก ห้องสมุดซีลีเนียม มีอยู่สำหรับ Python สิ่งนี้จะช่วยให้ฉันสามารถสร้างอินสแตนซ์ของ 'เบราว์เซอร์' - Chrome, Firefox, IE และอื่น ๆ - จากนั้นแสร้งทำเป็นว่าฉันใช้เบราว์เซอร์เพื่อเข้าถึงข้อมูลที่ฉันกำลังมองหา และถ้าฉันไม่ต้องการให้เบราว์เซอร์ปรากฏขึ้นจริงฉันสามารถสร้างเบราว์เซอร์ในโหมด“ ไม่มีหัว” ทำให้ผู้ใช้ทุกคนมองไม่เห็น
ในการเริ่มการทดลองฉันต้องตั้งค่าโปรเจ็กต์และหาทุกอย่างที่ต้องการ ฉันใช้เครื่อง Windows 10 และตรวจสอบให้แน่ใจว่าฉันมี Python เวอร์ชันที่ค่อนข้างอัปเดตแล้ว (เป็นเวอร์ชัน 3.7.3) ฉันสร้างสคริปต์ Python เปล่าจากนั้นโหลดไลบรารีที่ฉันคิดว่าอาจจำเป็นโดยใช้ PIP (ตัวติดตั้งแพ็คเกจสำหรับ Python) หากฉันยังไม่ได้โหลดไลบรารี นี่คือไลบรารีหลักที่ฉันเริ่มต้นด้วย:
ฉันยังเพิ่มพารามิเตอร์การโทรบางตัวลงในสคริปต์ (โดยใช้ไลบรารี argparse) เพื่อให้ฉันสามารถเล่นกับชุดข้อมูลต่างๆเรียกสคริปต์จากบรรทัดคำสั่งพร้อมตัวเลือกต่างๆ ซึ่งรวมถึงรหัสลูกค้าจากเดือน / ปีและถึงเดือน / ปี
ตัวเลือกแรกที่ฉันต้องทำคือเบราว์เซอร์ใดที่ฉันจะบอกให้ใช้ Selenium ตามปกติแล้วฉันใช้ Chrome และสร้างขึ้นจากโครงการ Chromium โอเพ่นซอร์ส (ใช้โดยเบราว์เซอร์ Edge, Opera และ Amazon Silk) ฉันคิดว่าฉันจะลองก่อน
ฉันสามารถเริ่ม Chrome ในสคริปต์ได้โดยการเพิ่มส่วนประกอบไลบรารีที่ฉันต้องการจากนั้นออกคำสั่งง่ายๆสองสามคำ:
# Load selenium components from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait, Select from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException # Establish chrome driver and go to report site URL url = 'https://reportdata.mytestsite.com/transactionSearch.jsp' driver = webdriver.Chrome() driver.get(url)
เนื่องจากฉันไม่ได้เปิดเบราว์เซอร์ในโหมด headless เบราว์เซอร์จึงปรากฏขึ้นจริงและฉันสามารถดูได้ว่ามันทำอะไร มันขอให้ฉันเลือกใบรับรองทันที (ซึ่งฉันได้ติดตั้งไว้ก่อนหน้านี้)
ปัญหาแรกที่ต้องจัดการคือใบรับรอง จะเลือกอันที่เหมาะสมและยอมรับเพื่อเข้าสู่เว็บไซต์ได้อย่างไร? ในการทดสอบสคริปต์ครั้งแรกของฉันฉันได้รับข้อความแจ้งนี้:
สิ่งนี้ไม่ดี ฉันไม่ต้องการคลิกปุ่มตกลงด้วยตนเองทุกครั้งที่เรียกใช้สคริปต์
ปรากฎว่าฉันสามารถหาวิธีแก้ปัญหานี้ได้โดยไม่ต้องเขียนโปรแกรม ในขณะที่ฉันหวังว่า Chrome จะสามารถส่งชื่อใบรับรองเมื่อเริ่มต้นได้ แต่คุณลักษณะนั้นก็ไม่มีอยู่จริง อย่างไรก็ตาม Chrome มีความสามารถในการเลือกใบรับรองโดยอัตโนมัติหากมีรายการบางรายการอยู่ในรีจิสทรีของ Windows คุณสามารถตั้งค่าให้เลือกใบรับรองแรกที่เห็นหรืออื่น ๆ ที่เฉพาะเจาะจงมากขึ้น เนื่องจากฉันโหลดใบรับรองเพียงใบเดียวฉันจึงใช้รูปแบบทั่วไป
ดังนั้นด้วยชุดดังกล่าวเมื่อฉันบอกให้ Selenium เปิด Chrome และมีข้อความแจ้งใบรับรองปรากฏขึ้น Chrome จะ 'เลือกอัตโนมัติ' ใบรับรองและดำเนินการต่อ
โอเคตอนนี้ฉันอยู่ในไซต์และมีแบบฟอร์มปรากฏขึ้นแจ้งให้ฉันพิมพ์รหัสลูกค้าและช่วงวันที่ของรายงาน
จากการตรวจสอบแบบฟอร์มในเครื่องมือสำหรับนักพัฒนา (F12) ฉันสังเกตเห็นว่ามีการนำเสนอแบบฟอร์มภายใน iframe ดังนั้นก่อนที่ฉันจะเริ่มกรอกแบบฟอร์มฉันต้อง 'เปลี่ยน' ไปใช้ iframe ที่เหมาะสมที่มีแบบฟอร์มอยู่ ในการทำเช่นนี้ฉันจึงเรียกใช้คุณลักษณะการสลับไปใช้ของซีลีเนียมดังนี้:
# Switch to iframe where form is frame_ref = driver.find_elements_by_tag_name('iframe')[0] iframe = driver.switch_to.frame(frame_ref)
ดีตอนนี้ฉันสามารถกำหนดส่วนประกอบเติมข้อมูลในฟิลด์รหัสลูกค้าและเลือกวันที่แบบเลื่อนลงได้:
# Find the Customer ID field and populate it element = driver.find_element_by_name('custId') element.send_keys(custId) # send a test id # Find and select the date drop-downs select = Select(driver.find_element_by_name('fromMonth')) select.select_by_visible_text(from_month) select = Select(driver.find_element_by_name('fromYear')) select.select_by_visible_text(from_year) select = Select(driver.find_element_by_name('toMonth')) select.select_by_visible_text(to_month) select = Select(driver.find_element_by_name('toYear')) select.select_by_visible_text(to_year)
สิ่งเดียวที่เหลืออยู่ในแบบฟอร์มคือการ 'คลิก' ปุ่มค้นหาเพื่อเริ่มการค้นหา นี่เป็นเรื่องยุ่งยากเล็กน้อยเนื่องจากปุ่มค้นหาดูเหมือนจะควบคุมโดย JavaScript และไม่ใช่ปุ่มประเภท 'ส่ง' แบบปกติ เมื่อตรวจสอบในเครื่องมือของนักพัฒนาฉันพบภาพปุ่มและสามารถรับ XPath ได้โดยคลิกขวา
จากนั้นติดอาวุธด้วยข้อมูลนี้ฉันพบองค์ประกอบบนหน้าเว็บจากนั้นคลิกที่มัน
# Find the ‘Find’ button, then click it driver.find_element_by_xpath('/html/body/table/tbody/tr[2]/td[1]/table[3]/tbody/tr[2]/td[2]/input').click()
และ voila มีการส่งแบบฟอร์มและข้อมูลปรากฏขึ้น! ตอนนี้ฉันสามารถขูดข้อมูลทั้งหมดในหน้าผลลัพธ์และบันทึกตามต้องการ หรือฉันจะ?
ก่อนอื่นฉันต้องจัดการกรณีที่การค้นหาไม่พบอะไรเลย นั่นค่อนข้างตรงไปตรงมา มันจะแสดงข้อความในแบบฟอร์มการค้นหาโดยไม่ต้องออกไปเช่น “ ไม่พบบันทึก” ฉันแค่ค้นหาสตริงนั้นและหยุดตรงนั้นถ้าฉันพบ
แต่หากได้ผลลัพธ์ข้อมูลจะแสดงใน divs พร้อมด้วยเครื่องหมายบวก (+) เพื่อเปิดธุรกรรมและแสดงรายละเอียดทั้งหมด ธุรกรรมที่เปิดแสดงเครื่องหมายลบ (-) ซึ่งเมื่อคลิกจะปิด div การคลิกที่เครื่องหมายบวกจะเรียก URL เพื่อเปิด div และปิดอันที่เปิดอยู่
ดังนั้นจึงจำเป็นต้องค้นหาเครื่องหมายบวกบนหน้ารวบรวม URL ถัดจากแต่ละรายการจากนั้นวนซ้ำเพื่อรับข้อมูลทั้งหมดสำหรับทุกธุรกรรม
# Loop through transactions and count links = driver.find_elements_by_tag_name('a') link_urls = [link.get_attribute('href') for link in links] thisCount = 0 isFirst = 1 for url in link_urls: if (url.find('GetXas.do?processId') >= 0): # URL to link to transactions if isFirst == 1: # already expanded + isFirst = 0 else: driver.get(url) # collapsed +, so expand # Find closest element to URL element with correct class to get tran type tran_type=driver.find_element_by_xpath('//*[contains(@href,'/retail/transaction/results/GetXas.do?processId=-1')]/following::td[@class='txt_75b_lmnw_T1R10B1']').text # Get transaction status status = driver.find_element_by_class_name('txt_70b_lmnw_t1r10b1').text # Add to count if transaction found if (tran_type in ['Move In','Move Out','Switch']) and (status == 'Complete'): thisCount += 1
ในโค้ดด้านบนฟิลด์ที่ฉันดึงข้อมูลคือประเภทธุรกรรมและสถานะจากนั้นเพิ่มลงในการนับเพื่อกำหนดจำนวนธุรกรรมที่เหมาะสมกับกฎที่ระบุ อย่างไรก็ตามฉันสามารถดึงข้อมูลช่องอื่น ๆ ภายในรายละเอียดธุรกรรมได้เช่นวันที่และเวลาประเภทย่อย ฯลฯ
สำหรับโปรเจ็กต์นี้จำนวนถูกส่งกลับไปยังแอปพลิเคชันการโทร อย่างไรก็ตามข้อมูลดังกล่าวและข้อมูลอื่น ๆ ที่คัดลอกมาอาจถูกเก็บไว้ในไฟล์แบบแบนหรือฐานข้อมูลเช่นกัน
อาจมีอุปสรรคอื่น ๆ อีกมากมายในขณะที่ขูดเว็บไซต์สมัยใหม่ด้วยอินสแตนซ์เบราว์เซอร์ของคุณเอง แต่ส่วนใหญ่สามารถแก้ไขได้ นี่คือบางส่วน:
พยายามค้นหาบางสิ่งก่อนที่มันจะปรากฏขึ้น
ในขณะที่เรียกดูตัวเองคุณพบว่าคุณกำลังรอให้หน้าเว็บปรากฏขึ้นบ่อยเพียงใดบางครั้งอาจเป็นเวลาหลายวินาที สิ่งเดียวกันนี้สามารถเกิดขึ้นได้ในขณะที่นำทางแบบเป็นโปรแกรม คุณมองหาชั้นเรียนหรือองค์ประกอบอื่น ๆ แต่มันไม่มี!
โชคดีที่ซีลีเนียมมีความสามารถในการรอจนกว่าจะเห็นองค์ประกอบบางอย่างและสามารถหมดเวลาได้หากองค์ประกอบนั้นไม่ปรากฏขึ้นดังนี้:
element = WebDriverWait(driver, 10). until(EC.presence_of_element_located((By.ID, 'theFirstLabel')))
ผ่าน Captcha
บางไซต์ใช้ Captcha หรือคล้ายกันเพื่อป้องกันโรบ็อตที่ไม่ต้องการ (ซึ่งพวกเขาอาจคิดว่าคุณ) สิ่งนี้สามารถทำให้แดมเปอร์ในการขูดเว็บและทำให้ช้าลง
สำหรับข้อความแจ้งง่ายๆ (เช่น“ อะไรคือ 2 + 3?”) โดยทั่วไปแล้วสิ่งเหล่านี้สามารถอ่านและหาคำตอบได้ง่าย อย่างไรก็ตามสำหรับอุปสรรคขั้นสูงมีไลบรารีที่สามารถช่วยในการถอดรหัสได้ ตัวอย่างบางส่วนคือ 2 แคปช่า , ตายโดย Captcha และ บายพาส Captcha .
การเปลี่ยนแปลงโครงสร้างเว็บไซต์
เว็บไซต์มีวัตถุประสงค์เพื่อเปลี่ยนแปลง - และมักจะทำ นั่นคือเหตุผลที่เมื่อเขียนสคริปต์คัดลอกจึงควรคำนึงถึงสิ่งนี้เสมอ คุณจะต้องพิจารณาว่าจะใช้วิธีใดในการค้นหาข้อมูลและวิธีใดที่จะไม่ใช้ พิจารณาเทคนิคการจับคู่บางส่วนแทนที่จะพยายามจับคู่ทั้งวลี ตัวอย่างเช่นเว็บไซต์อาจเปลี่ยนข้อความจาก 'ไม่พบระเบียน' เป็น 'ไม่พบบันทึก' - แต่ถ้าการจับคู่ของคุณอยู่ใน 'ไม่มีระเบียน' คุณควรจะโอเค นอกจากนี้ให้พิจารณาว่าจะจับคู่กับ XPATH, ID, ชื่อ, ข้อความลิงก์, แท็กหรือชื่อคลาสหรือตัวเลือก CSS หรือไม่และมีโอกาสเปลี่ยนแปลงน้อยที่สุด
นี่เป็นการสาธิตสั้น ๆ เพื่อแสดงให้เห็นว่าเว็บไซต์เกือบทุกแห่งสามารถคัดลอกได้ไม่ว่าจะใช้เทคโนโลยีใดและเกี่ยวข้องกับความซับซ้อนใดก็ตาม โดยทั่วไปหากคุณสามารถเรียกดูไซต์ได้ด้วยตัวเองโดยทั่วไปจะสามารถคัดลอกได้
ตอนนี้เป็นข้อแม้ก็ไม่ได้หมายความว่าทุกเว็บไซต์ ควร ถูกขูด บางอย่างมีข้อ จำกัด ที่ถูกต้องตามกฎหมายและมีมากมาย คดีในศาล การตัดสินความถูกต้องตามกฎหมายของการคัดลอกเว็บไซต์บางแห่ง ในทางกลับกันไซต์บางแห่งยินดีและสนับสนุนให้ดึงข้อมูลจากเว็บไซต์ของตนและในบางกรณีก็มี API เพื่อให้ง่ายขึ้น
ไม่ว่าจะด้วยวิธีใดคุณควรตรวจสอบข้อกำหนดในการให้บริการก่อนเริ่มโครงการใด ๆ แต่ถ้าคุณทำไปข้างหน้ามั่นใจได้ว่าคุณจะได้งานทำ
แหล่งข้อมูลที่แนะนำสำหรับการขูดเว็บที่ซับซ้อน:
Python กลายเป็นภาษาที่ได้รับความนิยมมากที่สุดสำหรับการขูดเว็บด้วยเหตุผลหลายประการ สิ่งเหล่านี้รวมถึงความยืดหยุ่นความสะดวกในการเขียนโค้ดการพิมพ์แบบไดนามิกคอลเลกชันขนาดใหญ่ของไลบรารีเพื่อจัดการข้อมูลและการสนับสนุนเครื่องมือขูดที่พบบ่อยที่สุดเช่น Scrapy, Beautiful Soup และ Selenium
การขูดเว็บไม่ผิดกฎหมาย ข้อมูลส่วนใหญ่บนเว็บไซต์มีไว้สำหรับการบริโภคของประชาชน อย่างไรก็ตามเว็บไซต์บางแห่งมีข้อกำหนดและเงื่อนไขที่ห้ามดาวน์โหลดข้อมูลโดยชัดแจ้ง สิ่งที่ปลอดภัยที่ต้องทำคือพิจารณาข้อ จำกัด ที่โพสต์โดยเว็บไซต์ใด ๆ และตระหนักถึงทรัพย์สินทางปัญญาของผู้อื่น
Beautiful Soup เป็นไลบรารี Python ที่สร้างขึ้นโดยเฉพาะเพื่อดึงข้อมูลออกจากไฟล์ HTML หรือ XML ในทางกลับกันซีลีเนียมเป็นกรอบสำหรับการทดสอบเว็บแอปพลิเคชัน ช่วยให้สามารถสร้างอินสแตนซ์เบราว์เซอร์โดยใช้ไดรเวอร์จากนั้นใช้คำสั่งเพื่อนำทางเบราว์เซอร์ได้ด้วยตนเอง
เบราว์เซอร์ headless โดยพื้นฐานแล้วเป็นเบราว์เซอร์ที่ไม่มีส่วนต่อประสานกับผู้ใช้ที่สามารถสร้างโดยใช้โปรแกรมได้ สามารถออกคำสั่งเพื่อนำทางเบราว์เซอร์ได้ แต่จะไม่มีสิ่งใดสามารถมองเห็นได้ในขณะที่มีเบราว์เซอร์อยู่
XPATH (XML Path Language) คือไวยากรณ์เฉพาะที่สามารถใช้เพื่อนำทางผ่านไฟล์ HTML หรือ XML โดยการระบุและนำทางโหนด ขึ้นอยู่กับการแสดงโครงสร้างของเอกสาร นี่คือตัวอย่าง XPATH ที่แสดงถึงชื่อของผลิตภัณฑ์แรกในองค์ประกอบผลิตภัณฑ์: / products / product [1] / name