วันนี้การคลานเว็บเป็นเทคโนโลยีที่รู้จักกันดี แต่ยังมีความซับซ้อนมากมาย โปรแกรมรวบรวมข้อมูลเว็บอย่างง่ายยังคงยากที่จะแข่งขันกับเว็บไซต์ที่ทันสมัยที่พัฒนาโดยเทคโนโลยีที่ซับซ้อนต่าง ๆ เช่นการฝึกอบรม AJAX, XMLHTTPREQUEST, WebSockets, Sockets แฟลช ฯลฯ
ลองใช้ความต้องการขั้นพื้นฐานของเราในโครงการ HUBDOC เป็นตัวอย่างที่เรารวบรวมข้อมูลจำนวนบิลวันหมดอายุหมายเลขบัญชีและที่สำคัญที่สุด: PDF ของตั๋วเงินล่าสุดจากเว็บไซต์ของธนาคารสาธารณูปโภคและ บริษัท บัตรเครดิต สำหรับโครงการนี้ฉันเริ่มต้นด้วยโซลูชันที่ง่ายมาก (ไม่ได้ใช้ผลิตภัณฑ์เชิงพาณิชย์ที่มีราคาแพงที่เรากำลังประเมินในขณะนี้) - โครงการรวบรวมข้อมูลง่ายๆที่ฉันเคยทำกับ Perl ใน Messagelab/Symantec แต่ผลลัพธ์ก็ไม่เป็นไปด้วยดีและผู้ส่งอีเมลขยะสร้างเว็บไซต์ที่ง่ายกว่าของธนาคารและสาธารณูปโภค
แล้วจะแก้ปัญหานี้ได้อย่างไร? เราเริ่มต้นด้วยห้องสมุดคำขอที่ยอดเยี่ยมที่พัฒนาขึ้นโดยใช้ Mikea ทำการร้องขอในเบราว์เซอร์และตรวจสอบว่าส่วนหัวคำขอใดถูกส่งออกไปในหน้าต่างเครือข่ายจากนั้นคัดลอกส่วนหัวคำขอเหล่านี้ลงในรหัส กระบวนการนี้ง่ายมาก มันเป็นเพียงการติดตามคำขอทั้งหมดจากการเข้าสู่ระบบไปยังการดาวน์โหลดไฟล์ PDF จากนั้นจำลองคำขอทั้งหมดจากกระบวนการนี้ เพื่อให้ง่ายต่อการจัดการกับสิ่งที่คล้ายกันและเพื่อให้นักพัฒนาเว็บมีเหตุผลมากขึ้นในการเขียนโปรแกรมรวบรวมข้อมูลฉันได้ส่งออกผลลัพธ์จาก HTML ไปยัง jQuery (โดยใช้ไลบรารี Cheatio ที่มีน้ำหนักเบา) ซึ่งทำให้งานคล้ายกันง่ายและทำให้ง่ายต่อการใช้ตัวเลือก CSS เพื่อเลือกองค์ประกอบในหน้า กระบวนการทั้งหมดถูกห่อเป็นกรอบซึ่งสามารถทำงานเพิ่มเติมได้เช่นการเก็บใบรับรองจากฐานข้อมูลการโหลดหุ่นยนต์แต่ละตัวและการสื่อสารกับ UI ผ่าน socket.io
สิ่งนี้ใช้ได้กับบางเว็บไซต์ แต่เป็นเพียงสคริปต์ JS ไม่ใช่รหัส Node.js ของฉันที่วางไว้บนเว็บไซต์ของพวกเขาโดย บริษัท เหล่านี้ พวกเขาสามารถเลเยอร์ปัญหาที่เหลือเพื่อจัดการกับความซับซ้อนทำให้เป็นเรื่องยากมากสำหรับคุณที่จะคิดออกว่าจะทำอย่างไรเพื่อให้ได้จุดข้อมูลการเข้าสู่ระบบ สำหรับบางไซต์ฉันพยายามที่จะได้รับโดยการรวมเข้ากับห้องสมุดคำขอ () สองสามวัน แต่มันก็ยังไร้ประโยชน์
หลังจากเกือบจะพังแล้วฉันค้นพบ Node-Phantomjs ซึ่งเป็นไลบรารีที่อนุญาตให้ฉันควบคุมเบราว์เซอร์ WebKit ที่ไม่มีหัวของ Phantomjs จากโหนด (หมายเหตุของนักแปล: ฉันไม่ได้คาดหวังคำนามที่สอดคล้องกัน ดูเหมือนว่าจะเป็นทางออกที่ง่าย แต่มีปัญหาบางอย่างที่ PhantomJs ไม่สามารถหลีกเลี่ยงได้:
1.phantomjs สามารถบอกคุณได้ว่าหน้านั้นโหลดแล้ว แต่คุณไม่สามารถระบุได้ว่ามีการเปลี่ยนเส้นทาง (เปลี่ยนเส้นทาง) ผ่าน JavaScript หรือ Meta Tags ในกระบวนการนี้หรือไม่ โดยเฉพาะอย่างยิ่งเมื่อ JavaScript ใช้ settimeout () เพื่อชะลอการโทร
2.PHANTOMJS ให้ตะขอ pageloadStarted ที่ช่วยให้คุณจัดการกับปัญหาที่กล่าวถึงข้างต้น แต่ฟังก์ชั่นนี้สามารถลดจำนวนนี้ได้ก็ต่อเมื่อคุณกำหนดจำนวนหน้าในการโหลดลดจำนวนนี้เมื่อโหลดแต่ละหน้าและให้การประมวลผลสำหรับการหมดเวลาที่เป็นไปได้ วิธีนี้สามารถใช้งานได้ แต่มันทำให้ผู้คนรู้สึกเหมือนแฮ็กเกอร์
3.PHANTOMJS ต้องการกระบวนการที่สมบูรณ์และเป็นอิสระสำหรับแต่ละหน้าเพื่อรวบรวมข้อมูลเพราะหากไม่ใช่กรณีนี้มันเป็นไปไม่ได้ที่จะแยกคุกกี้ระหว่างแต่ละหน้า หากคุณใช้กระบวนการ phantomjs เดียวกันเซสชันในหน้าเว็บที่เข้าสู่ระบบจะถูกส่งไปยังหน้าอื่น
4. ไม่สามารถใช้ phantomjs เพื่อดาวน์โหลดทรัพยากร - คุณสามารถบันทึกหน้าเป็น PNG หรือ PDF เท่านั้น สิ่งนี้มีประโยชน์ แต่ก็หมายความว่าเราจำเป็นต้องใช้วิธีการขอ () เพื่อดาวน์โหลด PDF
5. เนื่องจากเหตุผลข้างต้นฉันต้องหาวิธีแจกจ่ายคุกกี้จากเซสชัน Phantomjs ไปยังไลบรารีเซสชันของคำขอ () เพียงแจกจ่าย Document.cookie String แยกวิเคราะห์และฉีดเข้าไปในขวดคำขอคุกกี้ ()
6. การฉีดตัวแปรลงในเซสชันเบราว์เซอร์ไม่ใช่เรื่องง่าย ในการทำเช่นนี้ฉันต้องสร้างสตริงเพื่อสร้างฟังก์ชัน JavaScript
การคัดลอกรหัสมีดังนี้:
Robot.prototype.add_page_data = ฟังก์ชั่น (หน้า, ชื่อ, ข้อมูล) {
page.evaluate (
"function () {var" + name + "= window" + ชื่อ + "=" + json.stringify (data) + "}"
-
-
7. บางเว็บไซต์มักจะเต็มไปด้วยรหัสเช่น console.log () และพวกเขาจำเป็นต้องนิยามใหม่และส่งออกไปยังตำแหน่งที่เราต้องการ เพื่อทำสิ่งนี้ให้สำเร็จฉันทำสิ่งนี้:
การคัดลอกรหัสมีดังนี้:
if (! console.log) {
var iframe = document.createElement ("iframe");
document.body.appendchild (iframe);
console = window.frames [0] .console;
-
8. บางเว็บไซต์มักจะเต็มไปด้วยรหัสเช่น console.log () และพวกเขาจำเป็นต้องนิยามใหม่และส่งออกไปยังตำแหน่งที่เราต้องการ เพื่อทำสิ่งนี้ให้สำเร็จฉันทำสิ่งนี้:
การคัดลอกรหัสมีดังนี้:
if (! console.log) {
var iframe = document.createElement ("iframe");
document.body.appendchild (iframe);
console = window.frames [0] .console;
-
9. ไม่ใช่เรื่องง่ายที่จะบอกเบราว์เซอร์ว่าฉันคลิกที่แท็ก A เพื่อให้บรรลุสิ่งเหล่านี้ฉันได้เพิ่มรหัสต่อไปนี้:
การคัดลอกรหัสมีดังนี้:
var clickElement = window.clickelement = function (id) {
var a = document.getElementById (id);
var e = document.createeevent ("MouseEvents");
E.InitMouseVent ("คลิก", จริง, จริง, หน้าต่าง, 0, 0, 0, 0, เท็จ, เท็จ, เท็จ, เท็จ, 0, null);
A.Dispatchevent (e);
-
10. ฉันต้อง จำกัด การเกิดขึ้นพร้อมกันสูงสุดของเซสชันเบราว์เซอร์เพื่อให้แน่ใจว่าเราจะไม่ระเบิดเซิร์ฟเวอร์ ถึงกระนั้นข้อ จำกัด นี้ก็สูงกว่าโซลูชั่นเชิงพาณิชย์ที่มีราคาแพงมาก (หมายเหตุของนักแปล: นั่นคือการเกิดขึ้นพร้อมกันของโซลูชันเชิงพาณิชย์มากกว่าของโซลูชันนี้)
หลังจากทำงานทั้งหมดฉันมีวิธีแก้ปัญหาการรวบรวมข้อมูลที่ค่อนข้างดีสำหรับคำขอ Phantomjs + คุณต้องเข้าสู่ระบบด้วย Phantomjs ก่อนที่คุณจะสามารถกลับไปที่คำขอ () คำขอ มันจะใช้คุกกี้ที่ตั้งไว้ใน phantomjs เพื่อตรวจสอบเซสชันที่เข้าสู่ระบบ นี่เป็นชัยชนะครั้งใหญ่เพราะเราสามารถใช้สตรีมของคำขอ () เพื่อดาวน์โหลดไฟล์ PDF
แผนทั้งหมดคือการทำให้มันค่อนข้างง่ายสำหรับนักพัฒนาเว็บที่จะเข้าใจวิธีการใช้ตัวเลือก jQuery และ CSS เพื่อสร้างตัวรวบรวมข้อมูลสำหรับเว็บไซต์ที่แตกต่างกัน ฉันไม่ประสบความสำเร็จในการพิสูจน์ว่าความคิดนี้เป็นไปได้ แต่ฉันเชื่อว่ามันจะเกิดขึ้นเร็ว ๆ นี้