web-dev-qa-db-fra.com

Comment puis-je boucler les données de grattage pour plusieurs pages d'un site Web en utilisant python et beautifulsoup4

J'essaie de récupérer les données du site Web PGA.com pour obtenir un tableau de tous les terrains de golf aux États-Unis. Dans ma table CSV, je veux inclure le nom du terrain de golf, l'adresse, la propriété, le site Web et le numéro de téléphone. Avec ces données, je voudrais les géocoder et les placer dans une carte et en avoir une copie locale sur mon ordinateur

J'ai utilisé Python et Beautiful Soup4 pour extraire mes données. Site Web de la PGA. Je veux extraire TOUS LES PARCOURS DE GOLF mais mon script est limité à une seule page, je veux le boucler pour qu'il capture toutes les données des terrains de golf de toutes les pages trouvées sur le site de la PGA. Il y a environ 18000 pièces d'or cours et 900 pages pour capturer des données

Ci-dessous est mon script. J'ai besoin d'aide pour créer du code qui capturera TOUTES les données du site Web PGA et pas seulement un site mais plusieurs. De cette manière, il me fournira toutes les données des cours d'or aux États-Unis.

Voici mon script ci-dessous:

import csv
import requests 
from bs4 import BeautifulSoup
url = "http://www.pga.com/golf-courses/search?searchbox=Course+Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0"

r = requests.get(url)

soup = BeautifulSoup(r.content)

g_data1=soup.find_all("div",{"class":"views-field-nothing-1"})
g_data2=soup.find_all("div",{"class":"views-field-nothing"})

courses_list=[]

for item in g_data2:
     try:
          name=item.contents[1].find_all("div",{"class":"views-field-title"})[0].text
     except:
          name=''
     try:
          address1=item.contents[1].find_all("div",{"class":"views-field-address"})[0].text
     except:
          address1=''
     try:
          address2=item.contents[1].find_all("div",{"class":"views-field-city-state-Zip"})[0].text
     except:
          address2=''
     try:
          website=item.contents[1].find_all("div",{"class":"views-field-website"})[0].text
     except:
          website=''   
     try:
          Phonenumber=item.contents[1].find_all("div",{"class":"views-field-work-phone"})[0].text
     except:
          Phonenumber=''      

     course=[name,address1,address2,website,Phonenumber]
     courses_list.append(course)

     with open ('filename5.csv','wb') as file:
          writer=csv.writer(file)
          for row in courses_list:
               writer.writerow(row)    

#for item in g_data1:
     #try:
          #print item.contents[1].find_all("div",{"class":"views-field-counter"})[0].text
     #except:
          #pass  
     #try:
          #print item.contents[1].find_all("div",{"class":"views-field-course-type"})[0].text
     #except:
          #pass

#for item in g_data2:
   #try:
      #print item.contents[1].find_all("div",{"class":"views-field-title"})[0].text
   #except:
      #pass
   #try:
      #print item.contents[1].find_all("div",{"class":"views-field-address"})[0].text
   #except:
      #pass
   #try:
      #print item.contents[1].find_all("div",{"class":"views-field-city-state-Zip"})[0].text
   #except:
      #pass

Ce script n'en capture que 20 à la fois et je veux capturer le tout dans un script qui représente 18 000 terrains de golf et 900 pages à gratter.

8
Gonzalo68

La recherche sur le site Web de la PGA comporte plusieurs pages, l'url suit le modèle:

http://www.pga.com/golf-courses/search?page=1 # Additional info after page parameter here

cela signifie que vous pouvez lire le contenu de la page, puis modifier la valeur de la page par 1, et lire la page suivante .... et ainsi de suite.

import csv
import requests 
from bs4 import BeautifulSoup
for i in range(907):      # Number of pages plus one 
    url = "http://www.pga.com/golf-courses/search?page={}&searchbox=Course+Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0".format(i)
    r = requests.get(url)
    soup = BeautifulSoup(r.content)

    # Your code for each individual page here 
8
liamdiprose

si vous lisez toujours ce post, vous pouvez également essayer ce code ....

from urllib.request import urlopen
from bs4 import BeautifulSoup

file = "Details.csv"
f = open(file, "w")
Headers = "Name,Address,City,Phone,Website\n"
f.write(Headers)
for page in range(1,5):
    url = "http://www.pga.com/golf-courses/search?page={}&searchbox=Course%20Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0".format(page)
    html = urlopen(url)
    soup = BeautifulSoup(html,"html.parser")
    Title = soup.find_all("div", {"class":"views-field-nothing"})
    for i in Title:
        try:
            name = i.find("div", {"class":"views-field-title"}).get_text()
            address = i.find("div", {"class":"views-field-address"}).get_text()
            city = i.find("div", {"class":"views-field-city-state-Zip"}).get_text()
            phone = i.find("div", {"class":"views-field-work-phone"}).get_text()
            website = i.find("div", {"class":"views-field-website"}).get_text()
            print(name, address, city, phone, website)
            f.write("{}".format(name).replace(",","|")+ ",{}".format(address)+ ",{}".format(city).replace(",", " ")+ ",{}".format(phone) + ",{}".format(website) + "\n")
        except: AttributeError
f.close()

où il est écrit plage (1,5) changez cela avec 0, à la dernière page, et vous obtiendrez tous les détails en CSV, j'ai essayé très dur d'obtenir vos données au format approprié mais c'est difficile :).

3
Mr.Bones

Vous mettez un lien vers une seule page, cela ne va pas parcourir chacune d'elles.

Page 1:

url = "http://www.pga.com/golf-courses/search?searchbox=Course+Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0"

Page 2:

http://www.pga.com/golf-courses/search?page=1&searchbox=Course%20Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0

Page 907: http://www.pga.com/golf-courses/search?page=906&searchbox=Course%20Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0

Puisque vous exécutez la page 1, vous n'en obtiendrez que 20. Vous devrez créer une boucle qui parcourra chaque page.

Vous pouvez commencer par créer une fonction qui fait une page, puis itérer cette fonction.

Juste après le search? dans l'url, à partir de la page 2, page=1 commence à augmenter jusqu'à la page 907 où il est page=906.

2
Leb

Eu ce même problème exact et les solutions ci-dessus n'ont pas fonctionné. J'ai résolu le mien en tenant compte des cookies. Une session de requêtes aide. Créez une session et elle extraira toutes les pages dont vous avez besoin en insérant un cookie dans toutes les pages numérotées.

import csv
import requests 
from bs4 import BeautifulSoup
url = "http://www.pga.com/golf-courses/search?searchbox=Course+Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0"

s = requests.Session()
r = s.get(url)
0
Mark M

J'ai remarqué que la première solution avait une répétition de la première instance, c'est parce que la page 0 et la page 1 sont la même page. Ce problème est résolu en spécifiant la page de démarrage dans la fonction de plage. Exemple ci-dessous ...

     for i in range(1, 907):     #Number of pages plus one
        url = "http://www.pga.com/golf-courses/search?page={}&searchbox=Course+Name&searchbox_Zip=ZIP&distance=50&price_range=0&course_type=both&has_events=0".format(i)
        r = requests.get(url)
        soup = BeautifulSoup(r.content, "html5lib")   #Can use whichever parser you prefer

# Your code for each individual page here 
0
Kurtis Pykes