จะกำจัดรายชื่อผู้เล่นตัวจริงของ NBA ได้อย่างไร?

ฉันยังใหม่กับการขูดเว็บและอาจช่วยได้บ้าง ฉันต้องการขูดรายชื่อผู้เล่นตัวจริงของ NBA ทีม และตำแหน่งของผู้เล่นโดยใช้ Xpath ฉันแค่เริ่มต้นด้วยชื่อเพราะฉันประสบปัญหา

นี่คือรหัสของฉันจนถึงตอนนี้:

from urllib.request import urlopen
from lxml.html import fromstring 


url = "https://www.lineups.com/nba/lineups"

content = str(urlopen(url).read())
comment = content.replace("-->","").replace("<!--","")
tree = fromstring(comment)


for nba, bball_row in enumerate(tree.xpath('//tr[contains(@class,"t-content")]')):
    names = bball_row.xpath('.//span[@_ngcontent-c5="long-player-name"]/text()')[0]
    print(names)

ดูเหมือนว่าโปรแกรมจะทำงานโดยไม่มีข้อผิดพลาดแต่ชื่อไม่พิมพ์ออกมา คำแนะนำใดๆ เกี่ยวกับวิธีการแยกวิเคราะห์โดยใช้ Xpath อย่างมีประสิทธิภาพมากขึ้นจะได้รับการชื่นชมอย่างมาก ฉันพยายามยุ่งกับ Xpath helper และ Xpath Finder อาจมีเทคนิคบางอย่างเพื่อทำให้กระบวนการง่ายขึ้น ขอขอบคุณล่วงหน้าสำหรับเวลาและความพยายามของคุณ!


person Able Archer    schedule 23.10.2018    source แหล่งที่มา
comment
ข้อมูลที่คุณต้องการขูดกำลังถูกฉีดผ่าน Javascript คุณไม่สามารถขูดมันในแบบที่คุณทำอยู่ ลองหาซีลีเนียมดูครับ   -  person aris    schedule 23.10.2018
comment
ขอบคุณ @aris! ฉันจะตรวจสอบ Selenium และจะอัปเดตโค้ดของฉันหากฉันเข้าใจ   -  person Able Archer    schedule 23.10.2018


คำตอบ (1)


เนื้อหาที่จำเป็นซึ่งอยู่ภายในโหนด script ที่มีลักษณะเช่นนี้

<script nonce="STATE_TRANSFER_TOKEN">window['TRANSFER_STATE'] = {...}</script>

คุณสามารถลองทำสิ่งต่อไปนี้เพื่อแยกข้อมูลเป็นพจนานุกรม Python ธรรมดา:

import re
import json
import requests

source = requests.get("https://www.lineups.com/nba/lineups").text
dictionary = json.loads(re.search(r"window\['TRANSFER_STATE'\]\s=\s(\{.*\})<\/script>", source).group(1))

ทางเลือก: วางเอาต์พุตของ dictionary ที่นี่ แล้วคลิก "ตกแต่งให้สวยงาม" เพื่อดูข้อมูลเป็น JSON ที่อ่านได้ em>

จากนั้นคุณก็จะสามารถเข้าถึงค่าที่ต้องการได้โดยใช้คีย์ เช่น

for player in dictionary['https://api.lineups.com/nba/fetch/lineups/gateway']['data'][0]['home_players']:
    print(player['name'])

Kyrie Irving
Jaylen Brown
Jayson Tatum
Gordon Hayward
Al Horford

for player in dictionary['https://api.lineups.com/nba/fetch/lineups/gateway']['data'][0]['away_players']:
    print(player['name'])

D.J. Augustin
Evan Fournier
Jonathan Isaac
Aaron Gordon
Nikola Vucevic

อัปเดต

ฉันเดาว่าฉันเพิ่งทำให้มันซับซ้อนเกินไป :)

มันควรจะง่ายดังต่อไปนี้:

import requests

source = requests.get("https://api.lineups.com/nba/fetch/lineups/gateway").json()
for player in source['data'][0]['away_players']:
        print(player['name'])

อัปเดต 2

หากต้องการรับรายชื่อผู้เล่นตัวจริงของทีมทั้งหมดให้ใช้ด้านล่าง:

import requests

source = requests.get("https://api.lineups.com/nba/fetch/lineups/gateway").json()

for team in source['data']:
    print("\n%s players\n" % team['home_route'].capitalize())
    for player in team['home_players']:
        print(player['name'])
    print("\n%s players\n" % team['away_route'].capitalize())
    for player in team['away_players']:
        print(player['name'])
person Andersson    schedule 23.10.2018
comment
ทำได้ดีมาก คุณทราบได้อย่างไรว่าลิงก์ไปยังผลลัพธ์ที่ต้องการอาจอยู่ในสคริปต์ @sir Andersson ใด ๆ มีเคล็ดลับใดบ้างที่ควรทราบโดยใช้เครื่องมือ dev? - person SIM; 23.10.2018
comment
@SIM สิ่งแรกที่ต้องลองคือคัดลอกส่วนหนึ่งของข้อมูลที่ต้องการ -› แหล่งที่มาของหน้าเปิด (คลิกขวาที่หน้า - › ดูแหล่งที่มาของหน้า) -› Ctrl + F -› Ctrl + V หากไม่มีข้อมูลอยู่ ส่วนใหญ่น่าจะมาจาก XHR แต่ในกรณีนี้ข้อมูลอยู่ในโหนด script ในรูปแบบ JSON และคีย์แรกของ JSON คือลิงก์ไปยัง API ไม่มีเวทย์มนตร์ :) - person Andersson; 23.10.2018
comment
สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบตามที่โฆษณาไว้... ขอบคุณมาก @Andersson สำหรับความช่วยเหลือของคุณ การทำงานที่น่าตื่นตาตื่นใจ! =) - person Able Archer; 23.10.2018
comment
ฉันเพิ่งสังเกตเห็นว่าไม่มีการพิมพ์ทีมและผู้เล่นทั้งหมด ตอนแรกฉันคิดว่าเป็นเพราะสตาร์ทเตอร์ทั้งหมดยังมาไม่ถึง แต่ตอนนี้สตาร์ตเตอร์ได้รับการอัปเดตแล้ว ฉันเห็น 7 ทีมพิมพ์จากโค้ดด้านบน และทีมอันดับต้นๆ ไม่มีชื่อ คำแนะนำใด ๆ @Andersson? ฉันซาบซึ้งมากสำหรับความช่วยเหลือของคุณครับ - person Able Archer; 23.10.2018
comment
@AbleArcher อืม ... ฉันมี 6 ทีมเริ่มต้นสำหรับ 3 เกมปัจจุบัน ... คุณช่วยอธิบายให้ชัดเจนได้ไหมว่ามีอะไรผิดปกติกับผลลัพธ์เพราะฉันไม่แน่ใจว่าคุณต้องการได้ผลลัพธ์อะไร ตรวจสอบให้แน่ใจว่าคุณใช้โค้ดจากบล็อกการอัปเดตครั้งที่ 2 - person Andersson; 23.10.2018
comment
จริงๆ วันนี้มีแค่ 3 เกมครับ... ขออภัยด้วยครับ ผลลัพธ์ถูกต้องตามที่คุณระบุ ผู้เล่นและทีมเริ่มต้นทั้งหมดจะถูกพิมพ์ออกมา ดูเหมือนว่าผู้เล่นของ 76er จะพิมพ์ออกมาสองครั้ง ฉันเห็น Markelle Fultz พิมพ์หนึ่งครั้งที่ด้านบนและอีกครั้งภายใต้ 76ers นอกจากนั้นมันไม่มีที่ติ ฉันซาบซึ้งมากสำหรับความช่วยเหลือของคุณ @Andersson! ขอบคุณมากสำหรับประสบการณ์การเรียนรู้ =) - person Able Archer; 24.10.2018
comment
จริงๆ แล้วโค้ดนี้ทำงานได้อย่างสมบูรณ์แบบด้วย @Andersson ฉันเชื่อว่าฉันกำลังเพิ่มโค้ดอีกบรรทัดหนึ่ง ขอขอบคุณอีกครั้งสำหรับทุกคนที่ช่วย! - person Able Archer; 24.10.2018
comment
อัปเดต 2 ทำงานได้อย่างมีเสน่ห์ ปัญหาที่ฉันมีคือการเพิ่มการอัปเดต 1 และการอัปเดต 2 เข้าด้วยกัน รหัสนี้คือสิ่งที่ฉันกำลังมองหาอย่างแน่นอน - person Able Archer; 24.10.2018
comment
ขอบคุณอีกครั้ง @Andersson! คุณสามารถช่วยฉันเปลี่ยนโค้ดนี้เป็น dataframe ของ pandas ได้ไหม ฉันอยากจะนำเข้าข้อมูลนี้ไปยัง Excel ได้ - person Able Archer; 29.10.2018
comment
@AbleArcher ขออภัย ฉันไม่มีประสบการณ์มากนักกับ Pandas... คุณสามารถส่งตั๋วใหม่เกี่ยวกับปัญหานี้และเพิ่มแท็ก pandas ฉันแน่ใจว่ากูรู Pandas จะช่วยคุณ :) - person Andersson; 29.10.2018
comment
ขอบคุณคุณ @Andersson สำหรับเวลาของคุณ มันมีประโยชน์มาก =) - person Able Archer; 29.10.2018
comment
ฉันสามารถติดต่อคุณสำหรับงานในอนาคต @Andersson ได้ไหม ข้อมูลติดต่อของฉันอยู่ในโปรไฟล์ของฉัน - person Able Archer; 12.11.2018
comment
@AbleArcher หากคุณมีปัญหาในการเขียนโค้ดคุณสามารถโพสต์คำถามใหม่ได้ที่นี่ใน SO ฉันจะดูเมื่อฉันมีเวลา นอกจากนี้ยังมีผู้ใช้รายอื่นอีกมากมายที่สามารถช่วยเหลือได้ ขณะนี้ฉันกำลังทำโปรเจ็กต์อยู่ ดังนั้นฉันจึงไม่แน่ใจว่ามีเวลามากพอที่จะให้คำปรึกษา - person Andersson; 12.11.2018