在我的网页抓取技术中使用for
循环时,似乎出现了错误。
这是我的app.py
文件代码:
page_content = requests.get("http://books.toscrape.com/").content
parser = BookParser(page_content)
containers = parser.Content()
results = []
for container in containers:
name = container.getName()
link = container.getLink()
price = container.getPrice()
rating = container.getRating()
results.append({'name': name,
'link': link,
'price': price,
'rating': rating
})
print(results[4])
这是该函数的代码:
class BookParser(object):
RATINGS = {
'One': 1,
'Two': 2,
'Three': 3,
'Four': 4,
'Five': 5
}
def __init__(self, page):
self.soup = BeautifulSoup(page, 'html.parser')
def Content(self):
return self.soup.find_all("li",attrs={"class": 'col-xs-6'})
def getName(self):
return self.soup.find('h3').find('a')['title']
def getLink(self):
return self.soup.find('h3').find('a')['href']
def getPrice(self):
locator = BookLocator.PRICE
price = self.soup.select_one(locator).string
pattern = r"[0-9\.]*"
validator = re.findall(pattern, price)
return float(validator[1])
def getRating(self):
locator = BookLocator.STAR_RATING
rating = self.soup.select_one(locator).attrs['class']
rating_number = BookParser.RATINGS.get(rating[1])
return rating_number
最后,这是错误:
Traceback (most recent call last):
File "c:\Users\Utkarsh Kumar\Documents\Projects\milestoneP4\app.py", line 13, in <module>
name = container.getName()
TypeError: 'NoneType' object is not callable
我似乎不明白为什么getName()
函数返回无类型。
任何帮助都将受到高度赞赏,因为我是Web抓取的新手。
PS:不用for循环就可以正常使用
类似这样的东西:
name = parser.getName()
print(name)
答案 0 :(得分:2)
containers = parser.Content()
为您提供BS4元素列表,而不是BookParser
实例。您可以使用print(type(containers))
进行验证。
要继续使用.getName()
,您可以创建一个名为Book
的新类,移动.getName
并将所有相关方法移至该类,并传递从{{1}返回的列表项}方法(即.Content()
),然后您可以调用li.col-xs-6
类似的事情应该起作用:
book.getName()
答案 1 :(得分:1)
列表中的每本书都包含在以下li元素中:
<li class="col-xs-6 col-sm-4 col-md-3 col-lg-3">
<article class="product_pod">
<div class="image_container">
<a href="catalogue/a-light-in-the-attic_1000/index.html"><img src="media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg" alt="A Light in the Attic" class="thumbnail"></a>
</div>
<p class="star-rating Three">
<i class="icon-star"></i>
<i class="icon-star"></i>
<i class="icon-star"></i>
<i class="icon-star"></i>
<i class="icon-star"></i>
</p>
<h3><a href="catalogue/a-light-in-the-attic_1000/index.html" title="A Light in the Attic">A Light in the ...</a></h3>
<div class="product_price">
<p class="price_color">£51.77</p>
<p class="instock availability">
<i class="icon-ok"></i>
In stock
</p>
<form>
<button type="submit" class="btn btn-primary btn-block" data-loading-text="Adding...">Add to basket</button>
</form>
</div>
</article>
</li>
很抱歉格式不正确,但是您明白了。创建一个在单个列表元素而不是整个对象汤对象上操作的类。例如:
class BookParser:
def __init__(self, book_item ):
self.book_item = book_item
def getName( self ):
return self.book_item.find( path_to_name ).text
然后,您将首先解析页面,找到所有
soup = BeautifulSoup( url )
soup.find_all( path_to_book_elements )
books = []
for be in book_elements:
books.append( BookParser( be ))
books[0].getName() # A light in the Attic
books[1].getName() # Tripping on Velvet