จะขูดเว็บไซต์จาวาสคริปต์ใน Python ได้อย่างไร
ฉันกำลังพยายามขูดเว็บไซต์ ฉันได้ลองใช้สองวิธี แต่ทั้งสองไม่ได้ให้ซอร์สโค้ดเว็บไซต์แบบเต็มที่ฉันกำลังมองหา ฉันพยายามคัดลอกชื่อข่าวจาก URL ของเว็บไซต์ที่ให้ไว้ด้านล่าง
URL: "https://www.todayonline.com/"
นี่เป็นสองวิธีที่ฉันได้ลอง แต่ล้มเหลว
วิธีที่ 1: ซุปสวย
tdy_url = "https://www.todayonline.com/"
page = requests.get(tdy_url).text
soup = BeautifulSoup(page)
soup # Returns me a HTML with javascript text
soup.find_all('h3')
### Returns me empty list []
วิธีที่ 2: Selenium + BeautifulSoup
tdy_url = "https://www.todayonline.com/"
options = Options()
options.headless = True
driver = webdriver.Chrome("chromedriver",options=options)
driver.get(tdy_url)
time.sleep(10)
html = driver.page_source
soup = BeautifulSoup(html)
soup.find_all('h3')
### Returns me only less than 1/4 of the 'h3' tags found in the original page source
กรุณาช่วย. ฉันได้ลองขูดเว็บไซต์ข่าวอื่น ๆ แล้วมันง่ายกว่ามาก ขอขอบคุณ.
คำตอบ
คุณสามารถเข้าถึงข้อมูลผ่าน API (ดูแท็บเครือข่าย):
ตัวอย่างเช่น,
import requests
url = "https://www.todayonline.com/api/v3/news_feed/7"
data = requests.get(url).json()
มีหลายวิธีในการรวบรวมเนื้อหาของหน้าเว็บที่มี Javascript
- ใช้
seleniumกับโปรแกรมควบคุมเว็บ Firefox - ใช้เบราว์เซอร์ headless กับ
phantomJS - การเรียก API โดยใช้ไคลเอ็นต์ REST หรือ
requestsไลบรารีpython
คุณต้องทำวิจัยของคุณก่อน
ฉันจะแนะนำวิธีการที่ค่อนข้างง่าย
import requests
from bs4 import BeautifulSoup as bs
page = requests.get('https://www.todayonline.com/googlenews.xml').content
soup = bs(page)
news = [i.text for i in soup.find_all('news:title')]
print(news)
เอาท์พุท
['DBS named world’s best bank by New York-based financial publication',
'Russia has very serious questions to answer on Navalny - UK',
"Exclusive: 90% of China's Sinovac employees, families took coronavirus vaccine - CEO",
'Three militants killed after fatal attack on policeman in Tunisia',
.....]
นอกจากนี้คุณสามารถตรวจสอบหน้า XML สำหรับข้อมูลเพิ่มเติมได้หากจำเป็น
ปล. ตรวจสอบความสอดคล้องก่อนทิ้งเว็บไซต์ทุกครั้ง :)
ข้อมูลข่าวสารบนเว็บไซต์ที่คุณพยายามขูดนั้นดึงมาจากเซิร์ฟเวอร์โดยใช้ JavaScript (เรียกว่าXHR - XMLHttpRequest ) กำลังเกิดขึ้นแบบไดนามิกในขณะที่หน้าเว็บกำลังโหลดหรือกำลังเลื่อน ดังนั้นข้อมูลนี้จะไม่ถูกส่งกลับภายในเพจที่เซิร์ฟเวอร์ส่งคืน
ในตัวอย่างแรกคุณจะได้รับเฉพาะหน้าที่ส่งคืนโดยเซิร์ฟเวอร์ - โดยไม่มีข่าว แต่มี JS ที่ควรจะได้รับ ทั้งคำขอและ BeautifulSoup ไม่สามารถรัน JS ได้
อย่างไรก็ตามคุณสามารถลองสร้างคำขอที่ได้รับชื่อข่าวจากเซิร์ฟเวอร์ด้วยคำขอ Python ทำตามขั้นตอนต่อไปนี้:
- DevTools เปิดเบราว์เซอร์ของคุณ (โดยปกติคุณจะต้องกดF12หรือCtrl+ Shit+ Iสำหรับที่) และจะดูที่การร้องขอที่จะได้รับข่าวจากชื่อเซิร์ฟเวอร์ บางครั้งมันง่ายกว่าการขูดเว็บด้วย BeautifulSoup นี่คือภาพหน้าจอ (Firefox):
คัดลอกลิงก์คำขอ (คลิกขวา -> คัดลอก -> คัดลอกลิงก์)
requests.get(...)และผ่านมันไปได้รับ
.json()การร้องขอ มันจะส่งคืนคำสั่งที่ใช้งานง่าย เพื่อให้เข้าใจโครงสร้างของ dict ได้ดีขึ้นฉันขอแนะนำให้ใช้pprintแทนการพิมพ์แบบธรรมดา หมายเหตุคุณต้องทำfrom pprint import pprintก่อนใช้งาน
นี่คือตัวอย่างของรหัสที่ได้รับชื่อจากข่าวหลักในหน้า:
import requests
nodes = requests.get("https://www.todayonline.com/api/v3/news_feed/7")\
.json()["nodes"]
for node in nodes:
print(node["node"]["title"])
หากคุณต้องการรวบรวมกลุ่มข่าวภายใต้คำอธิบายภาพคุณต้องเปลี่ยนหมายเลขหลังจากnews_feed/ใน URL คำขอ (เพื่อให้ได้มาคุณเพียงแค่กรองคำขอโดยใช้ "news_feed" ใน DevTools และเลื่อนหน้าข่าวลง)
บางครั้งเว็บไซต์จะมีการป้องกันบอท (แม้ว่าเว็บไซต์ที่คุณพยายามขูดจะไม่มีก็ตาม) ในกรณีเช่นนี้คุณอาจต้องทำตามขั้นตอนเหล่านี้ด้วย