2013-04-15 26 views
1

我想從網頁收集數據,有一堆選擇列表,我需要從中獲取 數據。這裏是頁面: - http://www.asusparts.eu/partfinder/Asus/All在一/ E系列/使用python和beautifulsoup的選擇菜單從網頁獲取數據

而且這是我到目前爲止有:

import glob, string 
from bs4 import BeautifulSoup 
import urllib2, csv 

for file in glob.glob("http://www.asusparts.eu/partfinder/*"): 

##-page to show all selections for the E-series-## 
selected_list = 'http://www.asusparts.eu/partfinder/Asus/All In One/E Series/' 

##- 
page = urllib2.urlopen(selected_list) 
soup = BeautifulSoup(page) 

##-page which shows results after selecting one option-## 
url = 'http://www.asusparts.eu/partfinder/Asus/All In One/E Series/ET10B' 


##-identify the id of select list which contains the E-series-## 
select = soup.find('select', id="myselectListModel") 
option_tags = select.findAll('option') 

##-omit first item in list as isn't part of the option-## 
option_tags = option_tags[1:] 

for option in option_tags: 
    open(url + option['value']) 


html = urllib2.urlopen("http://www.asusparts.eu/partfinder/") 

soup = BeautifulSoup(html) 

all = soup.find('div', id="accordion") 

我不知道如果我要回到正確的方法是什麼?由於所有的選擇菜單令人困惑。基本上我需要抓取 來自選定結果的所有數據,如圖像,價格,描述等。它們都包含在 一個div標籤中,其中包含所有結果,這些結果被命名爲'accordion',那麼它是否仍然會收集所有數據? 還是我需要深入挖掘這個div內的標籤?此外,我會喜歡搜索ID,而不是 類,因爲我可以一次性獲取所有數據。我會如何做到這一點從我上面?謝謝。如果我正確使用它,我也不確定glob函數嗎?

編輯

這裏是我編輯的代碼,沒有錯誤但回到我不知道,如果它返回所有的E系列機型?

import string, urllib2, urllib, csv, urlparse from bs4 import 
BeautifulSoup 


##-page which shows results after selecting one option-## 
url = 'http://www.asusparts.eu/partfinder/Asus/All In One/E Series/ET10B' 


base_url = 'http://www.asusparts.eu/' + url 

print base_url 

##-page to show all selections for the E-series-## 
selected_list = urllib.quote(base_url + '/Asus/All In One/E Series/ET10B') 
print urllib.quote(base_url + '/Asus/All In One/E Series/ET10B') 

#selected_list = 'http://www.asusparts.eu/partfinder/Asus/All In One/E Series/ET10B' 

##- 
page = urllib2.urlopen('http://www.asusparts.eu/partfinder/Asus/All%20In%20One/E%20Series') 
soup = BeautifulSoup(page) 

print soup 

##-identify the id of select list which contains the E-series-## 
select = soup.find('select', id="myselectListModel") 
option_tags = select.findAll('option') 

print option_tags 

##-omit first item in list as isn't part of the option-## 
option_tags = option_tags[1:] 

print option_tags 


for option in option_tags: 
    url + option['redirectvalue'] 

print " " + url + option['redirectvalue'] 
+0

什麼是你放在那裏的for循環?您需要修正縮進,顯示屬於循環中的內容以及不包含的內容。 –

+0

glob()只適用於本地文件,它不適用於URL。您需要一些其他方法來查明該網站上存在哪些網頁,這可能涉及解析。 –

+0

請看看我的編輯代碼 – ash

回答

1

首先,我想指出您在發佈的代碼中遇到的一些問題。首先,所有glob模塊通常不用於製作HTTP請求。這對遍歷指定路徑上的文件子集很有用,您可以閱讀關於它的更多信息in its docs

的第二個問題是,在該行:

for file in glob.glob("http://www.asusparts.eu/partfinder/*"): 

你有一個壓痕錯誤,因爲後面沒有縮進代碼。這會引發錯誤並阻止執行其他代碼。

另一個問題是,你正在爲你的變量使用一些python的「保留」名稱。對於變量名稱,千萬不要使用allfile等單詞。

最後,當您通過option_tags循環:

for option in option_tags: 
    open(url + option['value']) 

open語句將嘗試打開本地文件的路徑是url + option['value']。這可能會引發錯誤,因爲我懷疑你會在該位置有文件。另外,你應該知道你沒有對這個打開的文件做任何事情。

好的,對評論足夠了。我看了一下華碩的頁面,我想我已經知道你想要完成什麼。根據我的理解,您想要在華碩頁面上爲每個計算機型號提供部件列表(圖片,文本,價格等)。每個型號都有位於唯一URL的部分列表(例如:http://www.asusparts.eu/partfinder/Asus/Desktop/B%20Series/BM2220)。這意味着您需要能夠爲每個模型創建此唯一的URL。爲了使事情更加複雜,每個零件類別都是動態加載的,因此例如「冷卻」部分的零件在您點擊「冷卻」鏈接之前不會加載。這意味着我們有兩個部分的問題:1)獲取所有有效的(品牌,類型,家族,模型)組合以及2)找出如何加載給定模型的所有零件。

我很無聊,並決定寫一個簡單的程序,將照顧大多數繁重的工作。這不是那裏最優雅的事情,但它會完成工作。步驟1)在get_model_information()中完成。步驟2)在parse_models()中照顧,但稍微不太明顯。看看華碩網站,無論何時點擊一個部分子部分,都會運行JavaScript函數getProductsBasedOnCategoryID(),這會對格式化的PRODUCT_URL(參見下文)進行ajax調用。響應是一些JSON信息,用於填充您單擊的部分。

import urllib2 
import json 
import urlparse 
from bs4 import BeautifulSoup 

BASE_URL = 'http://www.asusparts.eu/partfinder/' 
PRODUCTS_URL = 'http://json.zandparts.com/api/category/GetCategories/'\ 
       '44/EUR/{model}/{family}/{accessory}/{brand}/null/' 
ACCESSORIES = ['Cable', 'Cooling', 'Cover', 'HDD', 'Keyboard', 'Memory', 
       'Miscellaneous', 'Mouse', 'ODD', 'PS', 'Screw'] 


def get_options(url, select_id): 
    """ 
    Gets all the options from a select element. 
    """ 
    r = urllib2.urlopen(url) 
    soup = BeautifulSoup(r) 
    select = soup.find('select', id=select_id) 
    try: 
     options = [option for option in select.strings] 
    except AttributeError: 
     print url, select_id, select 
     raise 
    return options[1:] # The first option is the menu text 


def get_model_information(): 
    """ 
    Finds all the models for each family, all the families and models for each 
    type, and all the types, families, and models for each brand. 

    These are all added as tuples (brand, type, family, model) to the list 
    models. 
    """ 
    model_info = [] 

    print "Getting brands" 
    brand_options = get_options(BASE_URL, 'mySelectList') 

    for brand in brand_options: 
     print "Getting types for {0}".format(brand) 
     # brand = brand.replace(' ', '%20') # URL encode spaces 
     brand_url = urlparse.urljoin(BASE_URL, brand.replace(' ', '%20')) 
     types = get_options(brand_url, 'mySelectListType') 

     for _type in types: 
      print "Getting families for {0}->{1}".format(brand, _type) 
      bt = '{0}/{1}'.format(brand, _type) 
      type_url = urlparse.urljoin(BASE_URL, bt.replace(' ', '%20')) 
      families = get_options(type_url, 'myselectListFamily') 

      for family in families: 
       print "Getting models for {0}->{1}->{2}".format(brand, 
                   _type, family) 
       btf = '{0}/{1}'.format(bt, family) 
       fam_url = urlparse.urljoin(BASE_URL, btf.replace(' ', '%20')) 
       models = get_options(fam_url, 'myselectListModel') 

       model_info.extend((brand, _type, family, m) for m in models) 

    return model_info 


def parse_models(model_information): 
    """ 
    Get all the information for each accessory type for every 
    (brand, type, family, model). accessory_info will be the python formatted 
    json results. You can parse, filter, and save this information or use 
    it however suits your needs. 
    """ 

    for brand, _type, family, model in model_information: 
     for accessory in ACCESSORIES: 
      r = urllib2.urlopen(PRODUCTS_URL.format(model=model, family=family, 
               accessory=accessory, 
               brand=brand,)) 
      accessory_info = json.load(r) 
      # Do something with accessory_info 
      # ... 


def main(): 
    models = get_model_information() 
    parse_models(models) 


if __name__ == '__main__': 
    main() 

最後,一面說明。我已經放棄urllib2以支持requests庫。我個人認爲提供更多的功能和更好的語義,但你可以使用任何你想要的。

+0

哇...非常感謝您的詳細答案,我已經嘗試過這種方式,但它是一種痛苦的說,它無法找到模塊請求,即使我安裝它,所以我恢復使用舊的方式,因爲這是教師想要它是..他們皺眉不同的方法,即使他們更好 - _-無論如何,我收集我需要創建一個唯一的URL每個模型,但是,不應該在option_tags: url +選項['redirectvalue']'的選項照顧這個?此外,我已經更改了我的代碼,但我不確定是否收集E系列的所有型號 – ash

+0

樂意提供幫助。您可以很容易地將請求更改回urllib2,只需將'requests.get()'的每個實例替換爲'urllib2.urlopen()'並用'json.load(r)'替換'r.json()'將需要json模塊)。你是對的,你可以直接從重定向值獲取URL。我之所以沒有這樣做,是因爲我意識到你不需要模型的URL來獲取產品。您需要知道(品牌,類型,家族,模型),並將該信息作爲URL存儲,這意味着更多的字符串格式。我編輯了我的答案,使用urllib2代替請求。 – FastTurtle

+0

Ahh ok..cheers。我忘了提及你從姐妹網站添加產品網址,zand部分讓我感到困惑 - 這是否有必要? – ash

相關問題