Python (BeautifulSoup) - For Loop ส่งคืนผลลัพธ์ทั้งหมดสำหรับหนึ่ง div แทนที่จะเป็นค่าเดียวที่คาดไว้

ฉันกำลังสร้างที่ขูดสุขอนามัยอาหาร ฉันมาถึงจุดที่สามารถรับชื่อและที่อยู่ของร้านอาหารทั้งหมดได้สำเร็จตามรหัสไปรษณีย์ที่ผู้ใช้ป้อน ฉันได้พยายามให้แสดงค่าระดับสุขอนามัยอาหารสำหรับผลลัพธ์แต่ละรายการด้วย

ค่านี้จะถูกจัดเก็บไว้บนหน้าเว็บด้วยวิธีต่อไปนี้:

<div class="rating-image" style="clear: right;">
                <a href="/th/business/abbey-community-college-newtownabbey-antrim-992915.html" title="View Details">
                    <img src="https://images.scoresonthedoors.org.uk//schemes/735/on_small.png" alt="5 (Very Good)">
                </a>
            </div>

ฉันกำลังพยายามแยกข้อความ img alt

รหัสของฉันอยู่ด้านล่าง:

import requests
import time
from bs4 import BeautifulSoup


class RestaurantScraper(object):

def __init__(self, pc):
    self.pc = pc        # the input postcode
    self.max_page = self.find_max_page()        # The number of page available
    self.restaurants = list()       # the final list of restaurants where the scrape data will at the end of process

def run(self):
    for url in self.generate_pages_to_scrape():
        restaurants_from_url = self.scrape_page(url)
        self.restaurants += restaurants_from_url     # we increment the  restaurants to the global restaurants list

def create_url(self):
    """
    Create a core url to scrape
    :return: A url without pagination (= page 1)
    """
    return "https://www.scoresonthedoors.org.uk/search.php?name=&address=&postcode=" + self.pc + \
           "&distance=1&search.x=8&search.y=6&gbt_id=0&award_score=&award_range=gt"

def create_paginated_url(self, page_number):
    """
    Create a paginated url
    :param page_number: pagination (integer)
    :return: A url paginated
    """
    return self.create_url() + "&page={}".format(str(page_number))

def find_max_page(self):
    """
    Function to find the number of pages for a specific search.
    :return: The number of pages (integer)
    """
    time.sleep(5)
    r = requests.get(self.create_url())
    soup = BeautifulSoup(r.content, "lxml")
    pagination_soup = soup.findAll("div", {"id": "paginator"})
    pagination = pagination_soup[0]
    page_text = pagination("p")[0].text
    return int(page_text.replace('Page 1 of ', ''))

def generate_pages_to_scrape(self):
    """
    Generate all the paginated url using the max_page attribute previously scraped.
    :return: List of urls
    """
    return [self.create_paginated_url(page_number) for page_number in range(1, self.max_page + 1)]

def scrape_page(self, url):
    """
    This is coming from your original code snippet. This probably need a bit of work, but you get the idea.
    :param url: Url to scrape and get data from.
    :return:
    """
    time.sleep(5)
    r = requests.get(url)
    soup = BeautifulSoup(r.content, "lxml")
    g_data = soup.findAll("div", {"class": "search-result"})
    ratings = soup.select('div.rating-image img[alt]')
    restaurants = list()
    for item in g_data:
        name = print (item.find_all("a", {"class": "name"})[0].text)
        restaurants.append(name)
        try:
            print (item.find_all("span", {"class": "address"})[0].text)
        except:
            pass
        for rating in ratings:
            bleh = rating['alt']
            print (bleh)
    return restaurants


if __name__ == '__main__':
pc = input('Give your post code')
scraper = RestaurantScraper(pc)
scraper.run()
print ("{} restaurants scraped".format(str(len(scraper.restaurants))))

วิธีที่ฉันพยายามรวบรวมคะแนนสุขอนามัยแต่ละรายการสำหรับร้านอาหารแต่ละแห่งคือการใช้ for loop ดังที่แสดงด้านล่าง:

 for rating in ratings:
            bleh = rating['alt']
            print (bleh)

ปัญหาคือเมื่อสคริปต์ถูกเรียกใช้ภายใต้ชื่อและที่อยู่ของร้านอาหารแต่ละแห่ง มันจะแสดงคะแนนด้านสุขอนามัยอาหารทั้งหมดสำหรับร้านอาหารทั้งหมดบนหน้าเว็บ ในขณะที่ฉันต้องการให้แต่ละร้านอาหารแสดงภายใต้ร้านอาหารแต่ละแห่ง

ผลลัพธ์ที่ไม่ถูกต้องของการให้คะแนนทั้งหมดที่แสดงอยู่

ฉันคิดว่านี่อาจเป็นตำแหน่งที่ไม่ถูกต้องของ for loop?

ขอบคุณมากสำหรับทุกคนที่ดูสิ่งนี้และทุกคนที่ให้คำแนะนำ


person Brendan Rodgers    schedule 16.02.2017    source แหล่งที่มา


คำตอบ (1)


ใช้งานได้แล้ว ดูเหมือนว่าฉันลืมเพิ่ม for loop สำหรับการให้คะแนนเพื่อลองยกเว้นบล็อก หลังจากเพิ่มลงในบล็อกนี้แล้ว คะแนนเดี่ยวสำหรับร้านอาหารแต่ละแห่งจะแสดงอย่างถูกต้อง

ด้านล่างนี้เป็นรหัสที่ใช้งานได้อย่างสมบูรณ์

import requests
import time
from bs4 import BeautifulSoup


class RestaurantScraper(object):

def __init__(self, pc):
    self.pc = pc        # the input postcode
    self.max_page = self.find_max_page()        # The number of page available
    self.restaurants = list()       # the final list of restaurants where the scrape data will at the end of process

def run(self):
    for url in self.generate_pages_to_scrape():
        restaurants_from_url = self.scrape_page(url)
        self.restaurants += restaurants_from_url     # we increment the  restaurants to the global restaurants list

def create_url(self):
    """
    Create a core url to scrape
    :return: A url without pagination (= page 1)
    """
    return "https://www.scoresonthedoors.org.uk/search.php?name=&address=&postcode=" + self.pc + \
           "&distance=1&search.x=8&search.y=6&gbt_id=0&award_score=&award_range=gt"

def create_paginated_url(self, page_number):
    """
    Create a paginated url
    :param page_number: pagination (integer)
    :return: A url paginated
    """
    return self.create_url() + "&page={}".format(str(page_number))

def find_max_page(self):
    """
    Function to find the number of pages for a specific search.
    :return: The number of pages (integer)
    """
    time.sleep(5)
    r = requests.get(self.create_url())
    soup = BeautifulSoup(r.content, "lxml")
    pagination_soup = soup.findAll("div", {"id": "paginator"})
    pagination = pagination_soup[0]
    page_text = pagination("p")[0].text
    return int(page_text.replace('Page 1 of ', ''))

def generate_pages_to_scrape(self):
    """
    Generate all the paginated url using the max_page attribute previously scraped.
    :return: List of urls
    """
    return [self.create_paginated_url(page_number) for page_number in range(1, self.max_page + 1)]

def scrape_page(self, url):
    """
    This is coming from your original code snippet. This probably need a bit of work, but you get the idea.
    :param url: Url to scrape and get data from.
    :return:
    """
    time.sleep(5)
    r = requests.get(url)
    soup = BeautifulSoup(r.content, "lxml")
    g_data = soup.findAll("div", {"class": "search-result"})
    ratings = soup.select('div.rating-image img[alt]')
    restaurants = list()
    for item in g_data:
        name = print (item.find_all("a", {"class": "name"})[0].text)
        restaurants.append(name)
        try:
            print (item.find_all("span", {"class": "address"})[0].text)
        except:
            pass
        try:
            for rating in ratings:
                bleh = rating['alt']
                print (bleh)[0].text
        except:
            pass
    return restaurants


if __name__ == '__main__':
pc = input('Give your post code')
scraper = RestaurantScraper(pc)
scraper.run()
print ("{} restaurants scraped".format(str(len(scraper.restaurants))))

ส่วนที่แก้ไขปัญหาคือ:

 try:
        for rating in ratings:
            bleh = rating['alt']
            print (bleh)[0].text
    except:
        pass
return restaurants
person Brendan Rodgers    schedule 16.02.2017