1
votes

Comment parcourir les liens HTML dans un tableau pour extraire des données de tableaux?

J'essaie de parcourir le tableau à l'adresse https://bgp.he.net/report / monde . Je voudrais parcourir chacun des liens HTML menant aux pages de pays, puis récupérer les données, puis passer à la liste suivante. J'utilise une belle soupe et je peux déjà saisir les données que je veux, mais je ne comprends pas vraiment comment parcourir la colonne HTML.

from bs4 import BeautifulSoup
import requests
import json


headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0'}

url = "https://bgp.he.net/country/LC"
html = requests.get(url, headers=headers)

country_ID = (url[-2:])
print("\n")

soup = BeautifulSoup(html.text, 'html.parser')
#print(soup)
data = []
for row in soup.find_all("tr")[1:]: # start from second row
    cells = row.find_all('td')
    data.append({
        'ASN': cells[0].text,
        'Country': country_ID,
        "Name": cells[1].text,
        "Routes V4": cells[3].text,
        "Routes V6": cells[5].text
    })



i = 0

with open ('table_attempt.txt', 'w') as r:
    for item in data:
        r.write(str(data[i]))
        i += 1
        r.write("\n")


print(data)

Je voudrais pouvoir rassembler les données de chaque pays dans un fichier texte écrit.


0 commentaires

3 Réponses :


0
votes

Je n'ai testé cela qu'avec les 3 premiers liens (j'ai eu une erreur avec UnicodeEncodeError mais j'ai corrigé cela et commenté où cela se trouvait dans le code).

from bs4 import BeautifulSoup
import requests
import json

#First get the list of countries urls

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0'}

url = "https://bgp.he.net/report/world"
html = requests.get(url, headers=headers)

soup = BeautifulSoup(html.text, 'html.parser')

table = soup.find('table', {'id':'table_countries'})
rows = table.find_all('tr')

country_urls = []

# Go through each row and grab the link. If there's no link, continue to next row
for row in rows:
    try:
        link = row.select('a')[0]['href']
        country_urls.append(link)
    except:
        continue


# Now iterate through that list
for link in country_urls:

    url = "https://bgp.he.net" + link
    html = requests.get(url, headers=headers)

    country_ID = (url[-2:])
    print("\n")

    soup = BeautifulSoup(html.text, 'html.parser')
    #print(soup)
    data = []
    for row in soup.find_all("tr")[1:]: # start from second row
        cells = row.find_all('td')
        data.append({
            'ASN': cells[0].text,
            'Country': country_ID,
            "Name": cells[1].text,
            "Routes V4": cells[3].text,
            "Routes V6": cells[5].text
        })



    i = 0
    print ('Writing from %s' %(url))

    # I added encoding="utf-8" because of an UnicodeEncodeError:
    with open ('table_attempt.txt', 'w', encoding="utf-8") as r:
        for item in data:
            r.write(str(data[i]))
            i += 1
            r.write("\n")


3 commentaires

C'est presque parfait pour ce dont j'ai besoin. Merci beaucoup. Cela réécrit cependant le fichier à chaque fois. Je veux ajouter chaque sortie de table à un fichier. Je crois que si je prends une liste de données et que j'écris des données dans cette boucle for, cela pourrait me rapprocher.


Ah ok. bonne prise, je n'y ai pas pensé. essayez de changer le mode d'écriture 'w' pour ajouter 'a' . Ce que je veux dire, c'est, changez avec open ('table_attempt.txt', 'w', encoding = "utf-8") comme r: en avec open ('table_attempt.txt', 'a', encoding = "utf-8") as r: répondez si cela fait l'affaire


Certainement travaillé. Au lieu d'un txt normal, j'ai décidé de passer à un vidage JSON. Vous pouvez voir mon code ci-dessous. J'ai également ajouté une autre sortie qui aiderait l'utilisateur à savoir ce qui se passe réellement car il faut trop environ 3 minutes pour terminer.



0
votes

Vous pouvez parcourir la table principale et envoyer une demande pour récupérer la liste "rapport":

import requests, re
from bs4 import BeautifulSoup as soup
headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0'}
def scrape_report(_id):
  _d = soup(requests.get(f'https://bgp.he.net/country/{_id}', headers=headers).text, 'html.parser')
  _headers = [i.text for i in _d.find_all('th')]
  _, *data = [[i.text for i in b.find_all('td')] for b in _d.find_all('tr')]
  return [dict(zip(_headers, i)) for i in data]

d = soup(requests.get('https://bgp.he.net/report/world', headers=headers).text, 'html.parser')
_, *_listings = [[re.sub('[\t\n]+', '', i.text) for i in b.find_all('td')] for b in d.find_all('tr')]
final_result = [{**dict(zip(['Name', 'Country', 'ASN'], [a, b, c])), 'data':scrape_report(b)} for a, b, c, *_ in _listings]


0 commentaires

0
votes
import requests
import json


headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0'}
url = "https://bgp.he.net/report/world"
html = requests.get(url, headers=headers)

soup = BeautifulSoup(html.text, 'html.parser')

#sorting through table
table = soup.find('table', {'id':'table_countries'})
rows = table.find_all('tr')

country_urls = []

#Grabbing urls from table
for row in rows:
    try:
        link = row.select('a')[0]['href']
        country_urls.append(link)
    except:
        continue


Total_URLs= len(country_urls)


print(Total_URLs, "counties to pull data from")
print("\n")

#Creating text file
with open('table_attempt.txt', 'w', encoding="utf-8") as r:
    json.dumps([])


#Looping through country url list
    for link in country_urls:

        url = "https://bgp.he.net" + link
        html = requests.get(url, headers=headers)

#Taking country identifier from url list
        country_ID = (url[-2:])

        soup = BeautifulSoup(html.text, 'html.parser')

        data = []

        i=0
        Total_URLs -= 1

#appending to file
        with open('ASN_Info.txt', 'a', encoding="utf-8") as r:
            for row in soup.find_all("tr")[1:]: # start from second row
                cells = row.find_all('td')
                data.append({
                    'ASN': cells[0].text,
                    'Country': country_ID,
                    "Name": cells[1].text,
                    "Routes V4": cells[3].text,
                    "Routes V6": cells[5].text
                })
                json.dump(data[i], r)
                i += 1
                r.write("\n")

            print('Currently writing from data from %s. %s countries left to pull data from.' %(country_ID, Total_URLs))

0 commentaires