2017-02-15 8 views
0

ユーザーが入力した郵便番号に基づいて美しいスープを使用して簡単なスクレーパーを作成してレストランの食品衛生評価を取得しました。コードは正しく動作し、URLからの結果を正しく取得します。Python - 最初のページ(美味しいスープ)だけでなく、すべてのページの結果を表示

私が助けが必要なのは、最初のページの結果だけでなく、すべての結果を表示する方法です。

私のコードは以下の通りです:

import requests 
from bs4 import BeautifulSoup 

pc = input("Please enter postcode") 

url = "https://www.scoresonthedoors.org.uk/search.php?name=&address=&postcode="+pc+"&distance=1&search.x=8&search.y=6&gbt_id=0&award_score=&award_range=gt" 
r = requests.get(url) 

soup = BeautifulSoup(r.content, "lxml") 
g_data = soup.findAll("div", {"class": "search-result"}) 

for item in g_data: 
    print (item.find_all("a", {"class": "name"})[0].text) 
try: 
    print (item.find_all("span", {"class": "address"})[0].text) 
except: 
    pass 
try: 
    print (item.find_all("div", {"class": "rating-image"})[0].text) 
except: 
    pass 

私が示すページがページ

https://www.scoresonthedoors.org.uk/search.php?award_sort=ALPHA&name=&address=BT147AL&x=0&y=0&page=2#results 

ための改ページコードと呼ばれるURL文字列内の変数に依存していることがURLを見て、発見しました[次のページ]ボタンは次のとおりです。

<a style="float: right" href="?award_sort=ALPHA&amp;name=&amp;address=BT147AL&amp;x=0&amp;y=0&amp;page=3#results" rel="next " title="Go forward one page">Next <i class="fa fa-arrow-right fa-3"></i></a> 

私のコードでhを見つける方法はありますか多くのページの結果が表示され、これらのページのそれぞれから結果を取得しますか?

URL文字列を変更して毎回 "page ="(forループなど)を変更するコードを持つか、ページ区切りリンクコードの情報を使用して解決策を見つける方法があるのが最善の解決策でしょうか?ヘルプを提供したり、この質問

答えて

1

あなたが実際に右の道を進んでいるを見て、誰のための

感謝します。あらかじめスクラップするためにページ単位のURLを生成するのは良いアプローチです。

私は実際にコード全体をほぼ書きました。あなたが見たいのは、最初にfind_max_page()ファンクションです。これはページング文字列から最大ページを取ることから成ります。この番号を使用すると、あなたが掻き取る必要のあるすべてのURLを生成し、それを1つずつスクレイプすることができます。

以下のコードを確認してください。ほとんどすべてがそこにあります。

import requests 
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) 
     """ 
     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: 
     """ 
     r = requests.get(url) 
     soup = BeautifulSoup(r.content, "lxml") 
     g_data = soup.findAll("div", {"class": "search-result"}) 

     restaurants = list() 
     for item in g_data: 
      name = item.find_all("a", {"class": "name"})[0].text 
      restaurants.append(name) 
      try: 
       print item.find_all("span", {"class": "address"})[0].text 
      except: 
       pass 
      try: 
       print item.find_all("div", {"class": "rating-image"})[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))) 
+0

scrape_page関数は元のコードです。それはいくつかの仕事を使うことができます。この機能がうまく構築されていることを確認してください。他のすべてはかなり準備ができています。このコードに関する質問は、私に知らせてください。 –

+0

ありがとうフィリップ、このコードは完全に動作しています。 –

関連する問題