Как мне соскоблить несколько изображений стран с игроков на трансференмаркет и при этом избежать двойного гражданства? - PullRequest
1 голос
/ 20 марта 2020

Я новичок в чистке, и мне помогли с большей частью моего кода, я не собираюсь придумывать или «писать правильный путь» сейчас, просто пытаюсь заставить его работать. Это для проекта на моей стажировке.

Я пытаюсь получить информацию о 500 самых ценных игроках на Transfermarkt . Мне удалось очистить имя, ценность, национальность, клуб, должность, имидж игрока и имидж клуба. Я также хочу, чтобы очистить изображения страны. Я хочу сохранить результаты в CSV, что я достиг. Но не с изображениями страны. Все остальные столбцы содержат 500 строк, но списки изображений стран содержат 1007. Это мое сообщение об ошибке:

`Traceback (most recent call last):
  File "c:/Users/cljkn/Desktop/Python scraper github/.vscode/Scraping Transfermarkt.py", line 60, in <module>
    df = pd.DataFrame({"Player":names,"Club":clubs, "Nationality":nats,"Position":position,"Value":values, "PlayerImgURL":playerURL,"ClubImgURL":clubURL,"CountryImgURL":natURL})
  File "C:\Users\cljkn\Desktop\Python scraper github\.venv\lib\site-packages\pandas\core\frame.py", line 435, in __init__
    mgr = init_dict(data, index, columns, dtype=dtype)
  File "C:\Users\cljkn\Desktop\Python scraper github\.venv\lib\site-packages\pandas\core\internals\construction.py", line 254, in init_dict
    return arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)       
  File "C:\Users\cljkn\Desktop\Python scraper github\.venv\lib\site-packages\pandas\core\internals\construction.py", line 64, in arrays_to_mgr
    index = extract_index(arrays)
  File "C:\Users\cljkn\Desktop\Python scraper github\.venv\lib\site-packages\pandas\core\internals\construction.py", line 365, in extract_index
    raise ValueError("arrays must all be same length")
ValueError: arrays must all be same length`

Я пробовал и пробовал несколько разных вещей. Я напечатал список несколько раз, чтобы увидеть, в чем может быть проблема, и кажется, что у некоторых игроков есть два флага по национальности, я думаю, что у них двойные гражданские корабли. Когда это происходит, происходит перерыв в исходном коде, и я попытался прочитать только первое значение, но я не могу заставить это работать. Я искал в Интернете решения, но не могу найти ничего, что бы соответствовало моим потребностям. Я пробовал решение, в котором я вхожу в профиль каждого игрока, а затем получаю изображение оттуда, но я не могу заставить это работать. Я не нашел ничего в Интернете, что поможет мне в этом. Я проверил дубликаты в моем списке, удалив их, это тоже мне не поможет.

Вот мой код, и, как я уже сказал, большинство не сделано мной. Проблема заключается в #CountryImgURL:

import requests
from bs4 import BeautifulSoup
import csv
import pandas as pd
import re

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0'
}

pages = range(1, 21)

names = []
values = []
nats = []
clubs = []
position = []
playerURL = []
clubURL=[]
natURL=[]


for page in pages:

    r = requests.get(
        "https://www.transfermarkt.co.uk/spieler-statistik/wertvollstespieler/marktwertetop?page=%d" % page, headers=headers)

    soup = BeautifulSoup(r.text, 'html.parser')
    pretty = soup.prettify()

    for table in soup.find_all('table', attrs={'class': 'inline-table'}):
        content = table.contents
        names.append(content[0].text)  # Name
        position.append(content[1].text)  # Position

    for value in soup.findAll("td", class_="rechts hauptlink"): #Value
        values.append(value.get_text(strip=True))

    for td in soup.findAll("td", class_="zentriert"): #Nationality
        inner_grp = []
        for item in td.findAll("img", class_="flaggenrahmen", title=re.compile("^(?!http).*")):
            if item.get('title'):
                inner_grp.append(item.get('title'))
        if inner_grp:
            nats.append(inner_grp)

    for club in soup.findAll("img", src=re.compile("^http"), class_="", title=True)[:25]: #Club
        clubs.append(club.get("alt"))

    for img in soup.find_all('img', class_='bilderrahmen-fixed'): #PlayerImageURL
        playerURL.append(img.get('src'))

    for img in soup.find_all("img", class_="flaggenrahmen"): #CountryImageURL
        natURL.append(img.get('src'))

    for img in soup.findAll("img", src=re.compile("^http"), class_="", title=True)[:25]: #ClubImgURL
        clubURL.append(img.get('src'))


df = pd.DataFrame({"Player":names,"Club":clubs, "Nationality":nats,"Position":position,"Value":values, "PlayerImgURL":playerURL,"ClubImgURL":clubURL,"CountryImgURL":natURL})

df.head()

df.to_csv (r'S:\_ALL\Internal Projects\Introduction_2020\Transfermarkt\PlayerDetails.csv', index = False, header=True)

print(df)

1 Ответ

0 голосов
/ 21 марта 2020

Как вы заметили, для национальности может быть более 1 страны. Вы добавляете несколько раз в список natUrl здесь:

for img in soup.find_all("img", class_="flaggenrahmen"): #CountryImageURL
    natURL.append(img.get('src'))

Таким образом, когда вы в конце создаете фрейм данных, списки не имеют одинакового размера, что приводит к несогласованности, например, player [x] будет иметь национальность [x + 1], потому что игрок [x-1] имел 2 национальности. Фактически, вам нужно добавить ровно один элемент на каждую итерацию, если вы хотите, чтобы все массивы имели одинаковый размер, и в вашем коде много l oop, возможно, добавляющих несколько значений на одну итерацию (если есть несколько тегов img)

Я сделал пример, используя только список понимания:

from bs4 import BeautifulSoup
import requests
import pandas as pd

result = []

for page in range(1, 21):

    r = requests.get("https://www.transfermarkt.co.uk/spieler-statistik/wertvollstespieler/marktwertetop",
        params= {"page": page},
        headers= {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0"}
    )
    soup = BeautifulSoup(r.content, "html.parser")

    tr = soup.find_all("tbody")[1].find_all("tr", recursive=False)

    result.extend([
        { 
            "Player": t[1].find_all("td")[1].text,
            "Club": t[4].find("img")["alt"],
            "Nationality": t[3].find("img")["alt"], # for all nationality : [ i["alt"] for i in t[3].find_all("img")], 
            "Position": t[1].find_all("td")[2].text,
            "Value": t[5].text.strip(),
            "PlayerImgURL": t[1].find_all("img")[0]["src"],
            "ClubImgURL": t[4].find("img")["src"],
            "CountryImgURL": t[3].find("img")["src"] # for all country url: [ i["src"] for i in t[3].find_all("img")]
        }
        for t in (t.find_all(recursive=False) for t in tr)
    ])

df = pd.DataFrame(result)

df.to_csv('test.csv', index = False, header=True)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...