2012-12-09 10 views
5

मैं आइटम डेटा प्रदर्शित करने वाली साइट पर वेबपृष्ठों को पार्स कर रहा हूं। इन वस्तुओं में लगभग 20 फ़ील्ड हैं जो हो सकते हैं या नहीं हो सकते हैं - कहें: मूल्य, मात्रा, अंतिम खरीदा गया, उच्च, निम्न, आदिसुंदर सूप आदेशों की एक श्रृंखला को छोड़ने/छोड़ने का सुरुचिपूर्ण तरीका?

मैं वर्तमान में आदेशों की एक श्रृंखला का उपयोग कर रहा हूं; ब्याज के प्रत्येक अलग क्षेत्र की तलाश के लिए soup.find('div',{'class':SOME_FIELD_OF_INTEREST}) की लगभग 20 लाइनें। (कुछ dddiv में हैं, span,, और इतने पर, तो यह मुश्किल है सिर्फ एक soup.find_all('div') आदेश करने के लिए।)

मेरा प्रश्न: क्या try और except सब कुछ इस तरह के देखने का कहना है कि कोड कर सकते हैं करने के लिए एक सुंदर तरीका है अधिक कॉम्पैक्ट या संक्षिप्त हो? अभी एक नमूना रेखा इस तरह दिखेगी:

try: 
    soup.find('div', {'id':'item-pic'}).img["src"] 
except: 
    "" 

मैं एक पंक्ति में सब कुछ गठबंधन करने की उम्मीद कर रहा था। मुझे नहीं लगता कि मैं सिंटैक्टिक रूप से कोशिश कर सकता हूं: <line of code> except: <code>, और मुझे यकीन नहीं है कि मैं वास्तव में कमांड चलाने के बिना try_command(soup.find('div',{'id':'item-pic'}).img["src"]) पर एक फ़ंक्शन कैसे लिखूंगा।

मुझे यह सुनना अच्छा लगेगा कि किसी के पास कोई सलाह है (इसमें शामिल है: "यह संभव नहीं है/व्यावहारिक, आगे बढ़ें")। :)

संपादित करें: थोड़ा सा बात करने के बाद, मुझे लगता है कि मैं देखना चाहता हूं कि इनलाइन अपवाद हैंडलिंग के लिए अच्छा अभ्यास क्या है, और यदि यह लेने का सही मार्ग है।

+0

मैं तुम्हें एक में भाग खोज रहे हैं (जैसा कि 'NoneType' object has no attribute '__getitem__' वास्तव में अपवाद आप को पकड़ने की कोशिश कर रहे हैं नहीं है, यह गुण का उपयोग करने के BeautifulSoup द्वारा इस्तेमाल किया वाक्य रचना का प्रतिफल है) पाठ, यह regexes के लिए एक नौकरी है। – eyquem

+0

क्या आप खूबसूरत सूप का उपयोग कर XPATH अभिव्यक्ति के बराबर चलाना चाहते हैं: '// div [@ id =" item-pic "]/img/@ src'? कृपया, अधिक उदाहरण प्रदान करें। क्या आपने [डॉक्स] पढ़ा है (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-the-tree)? कोशिश करें/छोड़कर 'यहां एक बुरा विचार जैसा लगता है। – jfs

+0

मैं थोड़ा xPath और BeautifulSoup के बीच असंगतता याद मेरे सिर के ऊपर बंद ... lemme कोशिश अभी ... – binarysolo

उत्तर

1

शायद ऐसा ही कुछ:

def try_these(start_obj, *args) : 
     obj = start_obj 
     for trythat in args : 
      if obj is None : 
       return None 
      try : 
       if isinstance(trythat, str) : 
        obj = getattr(obj, trythat) 
       else : 
        method, opts = trythat 
        obj = getattr(obj, method)(*opts) 
      except : 
       return None 
     return obj  
src = try_these(soup, ('find', ({'id':'item-pic'},),), 
         'img', 
         ('get', ('src',),)) 

जहां str पारित कर सकते हैं वस्तु या tuple (str विधि, टपल पैरामीटर) से विशेषता प्राप्त करने के लिए, अंत में आप None या परिणाम मिलेगा। मैं सूप से परिचित नहीं हूं इसलिए मुझे यकीन नहीं है कि get('src') एक अच्छा दृष्टिकोण होगा (संभवतः यह एक निर्देश नहीं है), वैसे भी आप आसानी से उस स्निपेट को केवल 'कॉल या अटार' से अधिक कुछ स्वीकार करने के लिए संशोधित कर सकते हैं।


अपने प्रश्न मैं सरल अजगर मॉड्यूल है कि इस तरह की स्थिति से निपटने के लिए मदद करता है लिखा से प्रेरित होकर, आप इसे here

import silentcrawler  

wrapped = silentcrawler.wrap(soup) 
# just return None on failure 
print wrapped.find('div', {'id':'item-pic'}).img["src"].value_ 

# or 
def on_success(value) : 
    print 'found value:', value 
wrapped = silentcrawler.wrap(soup, success=on_success) 
# call on_success if everything will be ok 
wrapped.find('div', {'id':'item-pic'}).img["src"].value_ 

है अधिक संभावनाएं

+0

चुपचाप के लिए +1, हालांकि यह एक शर्म की बात है कि यह एक रैपर ऑब्जेक्ट को वापस करने के बजाय कॉलबैक का उपयोग करता है। 'Try_these' समारोह और अधिक जटिल और ट्राई/excepts का एक सरल श्रृंखला की तुलना में कम सुरुचिपूर्ण लगता है .. – dbr

+0

कारण है कि यह शर्म की बात है मैं नहीं मिलता है, वैसे भी आप इसे इस्तेमाल करने के कुछ तरीके की है। कॉलबैक मेरे लिए उपयोगी था (सफलता और विफलता कॉलबैक है), लेकिन आप रैपर ऑब्जेक्ट, लपेटा ऑब्जेक्ट प्राप्त कर सकते हैं, आप डिफ़ॉल्ट मान सेट कर सकते हैं और जो कुछ भी आप चाहते हैं, मॉड्यूल से जुड़े छोटे दस्तावेज़ देखें: https://github.com/lupatus/silentcrawler – lupatus

+0

ओह, बेवकूफ मुझे। मैंने उदाहरण कोड को ठीक से नहीं पढ़ा, और याद किया कि पहली विधि वस्तु (या 'कोई नहीं') लौटाती है। कॉलबैक लग रहा था जैसे कि यह इस विशिष्ट मामले में अजीब होगा, लेकिन मूल्य लौटने \ o/ – dbr

1

अगर मैं सही समझ में पा सकते हैं, तो आप एक दिलचस्प वर्ग नाम के आधार पर कुछ फ़ील्ड ढूंढना चाहते हैं, लेकिन वे एक ही तत्व आवश्यक नहीं हैं (सभी <div> नहीं)

यदि हां, तो सुंदर सूप के साथ आप एक संकलित रेगेक्स (re.compile से कई मामलों में एक स्ट्रिंग के स्थान पर पास कर सकते हैं।उदाहरण के लिए:

print soup.findAll(re.compile(".*"), {'class': 'blah'}) 
# [<div class="blah"></div>, <span class="blah"></span>] 

हम सभी प्रासंगिक देख डोम तत्वों पर इस के लिए शुध्ध पाश जो छवि शामिल हो सकता है का उपयोग कर सकते हैं:

import re 
import urllib 

from BeautifulSoup import BeautifulSoup as BS 


html = """ 
<html> 
<body> 
<div class="blah"></div> 
<span class="blah"><img src="yay.jpg"></span> 
<span class="other"></div> 

</body> 
</html> 
""" 

def get_img_src(soup, cssclass): 
    for item in soup.findAll(re.compile(".*"), {'class': cssclass}): 
     if item.img is not None and 'src' in dict(item.img.attrs): 
      return item.img['src'] 


soup = BS(html) 
img = get_img_src(soup, cssclass = "blah") 
print img # outputs yay.jpg, or would return None if nothing was found 

यह बहस का मुद्दा है, लेकिन मुझे लगता है कि if चेकों का उपयोग करने में अधिक उपयुक्त है इस मामले में, क्योंकि item.img['src']

यह भी उतना ही इस तरह लिखा जा सकता है:

def get_img_src(soup, cssclass): 
    for item in soup.findAll(re.compile(".*"), {'class': cssclass}): 
     try: 
      return item.img['src'] 
     except TypeError: 
      pass 

..लेकिन यह TypeError यहाँ पकड़ने के लिए अजीब बात है

+0

सही है कि निफ्टी था लगता है - मैं चीजों regex भूल जाते हैं तो मैं डॉ (एम)। पारितोषिक के लिए धन्यवाद! हालांकि मेरी मुख्य समस्या यह अपवाद हैंडलिंग और अगर मैं इसे शैलीगत क्लीनर कर सकते हैं ... – binarysolo

+0

@binarysolo ओह, मैं सोच रहा था regex सुंदर ढंग से परिणाम आप के बाद कर रहे हैं पाने के लिए इस्तेमाल किया जा सकता .. लेकिन पूरी तरह से है कि थोड़ा लिखना भूल जवाब का! संपादित – dbr