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.
3 Réponses :
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")
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.
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]
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))