Python Web Scraping - เว็บไซต์แบบไดนามิก

ในบทนี้ให้เราเรียนรู้วิธีการขูดเว็บบนเว็บไซต์แบบไดนามิกและแนวคิดที่เกี่ยวข้องโดยละเอียด

บทนำ

การขูดเว็บเป็นงานที่ซับซ้อนและความซับซ้อนจะทวีคูณหากเว็บไซต์เป็นแบบไดนามิก จากการตรวจสอบความสามารถในการเข้าถึงเว็บทั่วโลกขององค์การสหประชาชาติมากกว่า 70% ของเว็บไซต์มีลักษณะที่ไม่หยุดนิ่งและพวกเขาพึ่งพา JavaScript สำหรับฟังก์ชันการทำงานของตน

ตัวอย่างเว็บไซต์แบบไดนามิก

ให้เราดูตัวอย่างของเว็บไซต์แบบไดนามิกและทราบว่าเหตุใดจึงยากที่จะขูด เราจะนำตัวอย่างการค้นหาจากเว็บไซต์ชื่อhttp://example.webscraping.com/places/default/search.แต่เราจะพูดได้อย่างไรว่าเว็บไซต์นี้มีลักษณะไดนามิก สามารถตัดสินได้จากผลลัพธ์ของสคริปต์ Python ต่อไปนี้ซึ่งจะพยายามขูดข้อมูลจากหน้าเว็บที่กล่าวถึงข้างต้น -

import re
import urllib.request
response = urllib.request.urlopen('http://example.webscraping.com/places/default/search')
html = response.read()
text = html.decode()
re.findall('(.*?)',text)

เอาต์พุต

[ ]

ผลลัพธ์ข้างต้นแสดงให้เห็นว่ามีดโกนตัวอย่างไม่สามารถดึงข้อมูลได้เนื่องจากองค์ประกอบ <div> ที่เราพยายามค้นหาว่างเปล่า

แนวทางการขูดข้อมูลจากเว็บไซต์แบบไดนามิก

เราได้เห็นว่ามีดโกนไม่สามารถขูดข้อมูลจากเว็บไซต์แบบไดนามิกได้เนื่องจากข้อมูลถูกโหลดแบบไดนามิกด้วย JavaScript ในกรณีเช่นนี้เราสามารถใช้สองเทคนิคต่อไปนี้ในการดึงข้อมูลจากเว็บไซต์ที่ขึ้นอยู่กับ JavaScript แบบไดนามิก -

  • JavaScript วิศวกรรมย้อนกลับ
  • การแสดงผล JavaScript

JavaScript วิศวกรรมย้อนกลับ

กระบวนการที่เรียกว่าวิศวกรรมย้อนกลับจะมีประโยชน์และช่วยให้เราเข้าใจว่าข้อมูลถูกโหลดแบบไดนามิกโดยหน้าเว็บอย่างไร

ในการดำเนินการนี้เราต้องคลิกไฟล์ inspect elementแท็บสำหรับ URL ที่ระบุ ต่อไปเราจะคลิกNETWORK เพื่อค้นหาคำขอทั้งหมดที่สร้างขึ้นสำหรับหน้าเว็บนั้นรวมถึง search.json ด้วยเส้นทางของ /ajax. แทนที่จะเข้าถึงข้อมูล AJAX จากเบราว์เซอร์หรือผ่านแท็บ NETWORK เราสามารถทำได้ด้วยความช่วยเหลือของการทำตามสคริปต์ Python ด้วย -

import requests
url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a')
url.json()

ตัวอย่าง

สคริปต์ด้านบนช่วยให้เราเข้าถึงการตอบสนอง JSON โดยใช้วิธี Python json ในทำนองเดียวกันเราสามารถดาวน์โหลดการตอบกลับสตริงดิบและโดยใช้เมธอด json.loads ของ python เราก็สามารถโหลดได้เช่นกัน เรากำลังทำสิ่งนี้ด้วยความช่วยเหลือของการทำตามสคริปต์ Python โดยพื้นฐานแล้วมันจะขูดทุกประเทศโดยค้นหาตัวอักษร 'a' จากนั้นวนซ้ำหน้าผลลัพธ์ของการตอบกลับ JSON

import requests
import string
PAGE_SIZE = 15
url = 'http://example.webscraping.com/ajax/' + 'search.json?page={}&page_size={}&search_term=a'
countries = set()
for letter in string.ascii_lowercase:
   print('Searching with %s' % letter)
   page = 0
   while True:
   response = requests.get(url.format(page, PAGE_SIZE, letter))
   data = response.json()
   print('adding %d records from the page %d' %(len(data.get('records')),page))
   for record in data.get('records'):countries.add(record['country'])
   page += 1
   if page >= data['num_pages']:
      break
   with open('countries.txt', 'w') as countries_file:
   countries_file.write('n'.join(sorted(countries)))

หลังจากเรียกใช้สคริปต์ข้างต้นเราจะได้ผลลัพธ์ต่อไปนี้และบันทึกจะถูกบันทึกไว้ในไฟล์ชื่อ countries.txt

เอาต์พุต

Searching with a
adding 15 records from the page 0
adding 15 records from the page 1
...

การแสดงผล JavaScript

ในส่วนก่อนหน้านี้เราได้ทำวิศวกรรมย้อนกลับบนหน้าเว็บว่า API ทำงานอย่างไรและเราจะใช้มันเพื่อดึงผลลัพธ์ในคำขอเดียวได้อย่างไร อย่างไรก็ตามเราสามารถเผชิญกับปัญหาต่อไปนี้ได้ในขณะที่ทำวิศวกรรมย้อนกลับ -

  • บางครั้งเว็บไซต์อาจเป็นเรื่องยากมาก ตัวอย่างเช่นหากเว็บไซต์สร้างด้วยเครื่องมือเบราว์เซอร์ขั้นสูงเช่น Google Web Toolkit (GWT) โค้ด JS ที่ได้จะถูกสร้างขึ้นโดยเครื่องและยากที่จะเข้าใจและทำวิศวกรรมย้อนกลับ

  • เฟรมเวิร์กระดับสูงบางอย่างเช่น React.js สามารถทำให้วิศวกรรมย้อนกลับเป็นเรื่องยากโดยการสรุปตรรกะ JavaScript ที่ซับซ้อนอยู่แล้ว

วิธีแก้ปัญหาข้างต้นคือการใช้เครื่องมือเรนเดอร์เบราว์เซอร์ที่แยกวิเคราะห์ HTML ใช้การจัดรูปแบบ CSS และเรียกใช้ JavaScript เพื่อแสดงหน้าเว็บ

ตัวอย่าง

ในตัวอย่างนี้สำหรับการแสดงผล Java Script เราจะใช้โมดูล Python Selenium ที่คุ้นเคย รหัส Python ต่อไปนี้จะแสดงหน้าเว็บด้วยความช่วยเหลือของ Selenium -

ขั้นแรกเราต้องนำเข้า webdriver จากซีลีเนียมดังนี้ -

from selenium import webdriver

ตอนนี้ให้เส้นทางของโปรแกรมควบคุมเว็บที่เราดาวน์โหลดตามความต้องการของเรา -

path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path = path)

ตอนนี้ให้ระบุ url ที่เราต้องการเปิดในเว็บเบราว์เซอร์นั้นตอนนี้ควบคุมโดยสคริปต์ Python ของเรา

driver.get('http://example.webscraping.com/search')

ตอนนี้เราสามารถใช้ ID ของกล่องเครื่องมือค้นหาเพื่อตั้งค่าองค์ประกอบเพื่อเลือก

driver.find_element_by_id('search_term').send_keys('.')

ต่อไปเราสามารถใช้สคริปต์ java เพื่อตั้งค่าเนื้อหากล่องเลือกได้ดังนี้ -

js = "document.getElementById('page_size').options[1].text = '100';"
driver.execute_script(js)

โค้ดบรรทัดต่อไปนี้แสดงให้เห็นว่าการค้นหาพร้อมที่จะคลิกบนหน้าเว็บ -

driver.find_element_by_id('search').click()

โค้ดบรรทัดถัดไปแสดงว่าจะรอ 45 วินาทีเพื่อให้คำขอ AJAX เสร็จสมบูรณ์

driver.implicitly_wait(45)

ตอนนี้สำหรับการเลือกลิงค์ประเทศเราสามารถใช้ตัวเลือก CSS ได้ดังนี้ -

links = driver.find_elements_by_css_selector('#results a')

ตอนนี้สามารถแยกข้อความของแต่ละลิงค์เพื่อสร้างรายชื่อประเทศ -

countries = [link.text for link in links]
print(countries)
driver.close()