Добавление для l oop к рабочему веб-скребку (Python и Beautifulsoup) - PullRequest
1 голос
/ 14 апреля 2020

У меня есть запрос, касающийся циклов и добавления одного к уже работающему веб-скребку для просмотра списка веб-страниц. То, что я смотрю на это, вероятно, две или три простые строки кода.

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

Справочная информация:

Я написал веб-скребок с использованием Python и Beautifulsoup, который успешно удалось взять веб-страницу с TransferMarkt.com и очистить все необходимые веб-ссылки. Сценарий состоит из двух частей:

  1. В первой части я беру веб-страницу для футбольной лиги, например Премьер-лиги, и извлекаю ссылки на веб-страницы для всех отдельных игроков. команды в таблице лиги и поместите их в список.
  2. Во второй части моего сценария я беру этот список отдельных команд и дополнительно извлекаю информацию о каждом из отдельных игроков для каждой команды, а затем присоединяюсь это вместе, чтобы сформировать один большой pandas DataFrame информации об игроке.

Мой вопрос касается того, как добавить для l oop в первую часть этого веб-скребка, чтобы не просто извлечь команду ссылки с одной веб-страницы лиги, но для извлечения ссылок из списка веб-страниц лиги.

Ниже я привел пример веб-страницы футбольной лиги, код моего веб-скребка и вывод.

Пример:

Пример веб-страницы для очистки (Премьер-лига - код GB1): https://www.transfermarkt.co.uk/jumplist/startseite/wettbewerb/gb1/plus/?saison_id=2019

Код (часть 1 из 2) - скрести инди ссылки на отдельные команды с веб-страницы лиги:

# Python libraries

##  Data Preprocessing
import pandas as pd

##  Data scraping libraries
from bs4 import BeautifulSoup
import requests


# Assign league by code, e.g. Premier League = 'GB1', to the list_league_selected variable
list_league_selected = 'GB1'


# Assign season by year to season variable e.g. 2014/15 season = 2014
season = '2019'


# Create an empty list to assign these values to
team_links = []


# Web scraper script

## Process League Table
headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'}
page = 'https://www.transfermarkt.co.uk/jumplist/startseite/wettbewerb/' + id + '/plus/?saison_id=' + season
tree = requests.get(page, headers = headers)
soup = BeautifulSoup(tree.content, 'html.parser')

## Create an empty list to assign these values to - team_links
team_links = []

## Extract all links with the correct CSS selector
links = soup.select("a.vereinprofil_tooltip")

## We need the location that the link is pointing to, so for each link, take the link location. 
## Additionally, we only need the links in locations 1, 3, 5, etc. of our list, so loop through those only
for i in range(1,59,3):
    team_links.append(links[i].get("href"))

## For each location that we have taken, add the website before it - this allows us to call it later
for i in range(len(team_links)):
    team_links[i] = "https://www.transfermarkt.co.uk" + team_links[i]


# View list of team weblinks assigned to variable - team_links
team_links

Вывод:
Извлеченные ссылки с примера веб-страницы (всего 20 ссылок, например, веб-страница, только 4):

team_links = ['https://www.transfermarkt.co.uk/manchester-city/startseite/verein/281/saison_id/2019',
 'https://www.transfermarkt.co.uk/fc-liverpool/startseite/verein/31/saison_id/2019',
 'https://www.transfermarkt.co.uk/tottenham-hotspur/startseite/verein/148/saison_id/2019',
 'https://www.transfermarkt.co.uk/fc-chelsea/startseite/verein/631/saison_id/2019',
...,
'https://www.transfermarkt.co.uk/sheffield-united/startseite/verein/350/saison_id/2019']

Используя этот список команд - team_links, я затем могу дополнительно извлекать информацию для всех игроков каждой команды с помощью следующего кода. Из этого вывода я могу создать pandas DataFrame для всей информации об игроках:

Код (часть 2 из 2) - очистить информацию об отдельных игроках, используя список team_links:

# Create an empty DataFrame for the data, df
df = pd.DataFrame()

# Run the scraper through each of the links in the team_links list
for i in range(len(team_links)):

    # Download and process the team page
    page = team_links[i]
    df_headers = ['position_number' , 'position_description' , 'name' , 'dob' , 'nationality' , 'value']
    pageTree = requests.get(page, headers = headers)
    pageSoup = BeautifulSoup(pageTree.content, 'lxml')

    # Extract all data
    position_number = [item.text for item in pageSoup.select('.items .rn_nummer')]
    position_description = [item.text for item in pageSoup.select('.items td:not([class])')]
    name = [item.text for item in pageSoup.select('.hide-for-small .spielprofil_tooltip')]
    dob = [item.text for item in pageSoup.select('.zentriert:nth-of-type(4):not([id])')]
    nationality = ['/'.join([i['title'] for i in item.select('[title]')]) for item in pageSoup.select('.zentriert:nth-of-type(5):not([id])')]
    value = [item.text for item in pageSoup.select('.rechts.hauptlink')]
    df_temp = pd.DataFrame(list(zip(position_number, position_description, name, dob, nationality, value)), columns = df_headers)
    df = df.append(df_temp)   # This last line of code is mine. It appends to temporary data to the master DataFrame, df

# View the pandas DataFrame
df

Мой вопрос к вам - добавление a для l oop к go через все лиги:

Что мне нужно сделать, это заменить * Переменная 1054 * присваивается индивидуальному коду лиги в первой части моего кода, и вместо нее используется значение от l oop до go через полный список кодов лиги - list_all_leagues. Этот список кодов лиги выглядит следующим образом:

list_all_leagues = ['L1', 'GB1', 'IT1', 'FR1', 'ES1']    # codes for the top 5 European leagues

Я прочитал несколько решений, но я изо всех сил пытаюсь заставить работать l oop и добавляю полный список веб-страниц команд на правильном часть. Я полагаю, что теперь я действительно близок к завершению моего скребка, и любой совет о том, как создать это для l oop, будет очень признателен!

Заранее спасибо за вашу помощь!

1 Ответ

2 голосов
/ 15 апреля 2020

На самом деле я потратил время на то, чтобы исправить много ошибок в вашем коде. и сократить большую дорогу. Ниже вы можете достичь своей цели.

Я считал, что находился под защитой от антибиотиков c (meant), что подразумевалось под requests.Session() для поддержания Session в течение моего l oop, что означает предотвращение TCP уровень защиты от blocking/refusing/dropping my packet/request while Scraping.

import requests
from bs4 import BeautifulSoup
import pandas as pd


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

leagues = ['L1', 'GB1', 'IT1', 'FR1', 'ES1']


def main(url):
    with requests.Session() as req:
        links = []
        for lea in leagues:
            print(f"Fetching Links from {lea}")
            r = req.get(url.format(lea), headers=headers)
            soup = BeautifulSoup(r.content, 'html.parser')
            link = [f"{url[:31]}{item.next_element.get('href')}" for item in soup.findAll(
                "td", class_="hauptlink no-border-links hide-for-small hide-for-pad")]
            links.extend(link)

        print(f"Collected {len(links)} Links")
        goals = []
        for num, link in enumerate(links):
            print(f"Extracting Page# {num +1}")
            r = req.get(link, headers=headers)
            soup = BeautifulSoup(r.content, 'html.parser')
            target = soup.find("table", class_="items")
            pn = [pn.text for pn in target.select("div.rn_nummer")]
            pos = [pos.text for pos in target.findAll("td", class_=False)]
            name = [name.text for name in target.select("td.hide")]
            dob = [date.find_next(
                "td").text for date in target.select("td.hide")]
            nat = [" / ".join([a.get("alt") for a in nat.find_all_next("td")[1] if a.get("alt")]) for nat in target.findAll(
                "td", itemprop="athlete")]
            val = [val.get_text(strip=True)
                   for val in target.select('td.rechts.hauptlink')]
            goal = zip(pn, pos, name, dob, nat, val)
            df = pd.DataFrame(goal, columns=[
                              'position_number', 'position_description', 'name', 'dob', 'nationality', 'value'])
            goals.append(df)

        new = pd.concat(goals)
        new.to_csv("data.csv", index=False)


main("https://www.transfermarkt.co.uk/jumplist/startseite/wettbewerb/{}/plus/?saison_id=2019")

Вывод: Просмотр онлайн

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...