在我的刮刀中使用lambda函数时遇到麻烦

时间:2018-03-15 13:24:22

标签: python python-3.x lambda web-scraping

我已经编写了一个脚本来解析craigslist中某些项目的名称和价格。我的刮刀中定义的xpath是工作的。问题是,当我尝试以通常方式刮取项目然后应用try/except块时,当某个价格的值为none时,我可以避免IndexError。我甚至尝试使用自定义功能使其工作并获得成功。

但是,在下面的代码段中,我想应用lambda函数来解决IndexError错误。我试过但不能成功。

顺便说一下,当我运行代码时它既不会取任何东西也不会抛出任何错误。

import requests
from lxml.html import fromstring

page = requests.get('http://bangalore.craigslist.co.in/search/rea?s=120').text
tree = fromstring(page)

# I wish to fix this function to make a go
get_val = lambda item,path:item.text if item.xpath(path) else ""

for item in tree.xpath('//li[@class="result-row"]'):
    link = get_val(item,'.//a[contains(@class,"hdrlnk")]')
    price = get_val(item,'.//span[@class="result-price"]')
    print(link,price)

1 个答案:

答案 0 :(得分:4)

首先,如果路径存在,则lambda函数get_val将返回项目的文本,而不是搜索节点的文本。这可能不是你想要的。如果想要返回与路径匹配的(第一个)元素的文本内容,您应该写:

get_val = lambda item, path: item.xpath(path)[0].text if item.xpath(path) else ""

请注意xpath会返回一个列表。我假设你在这个列表中只有一个元素。

输出是这样的:

...
Residential Plot @ Sarjapur Check Post ₨1000
Prestige dolce vita apartments in whitefield, Bangalore 
Brigade Golden Triangle, ₨12500000
Nikoo Homes, ₨6900000

但我认为你想要一个链接,而不是文本。如果是这种情况,请阅读以下内容。

好的,如何获得链接?如果您拥有锚a,则会在attibutes表中获得href(链接):a.attrib["href"]

据我了解,在价格的情况下,您需要文本,但在锚点的情况下,您需要一个特定属性的值href。这是lambdas的真实用法。像这样改写你的功能:

def get_val(item, path, l):
    return l(item.xpath(path)[0]) if item.xpath(path) else ""

参数l是应用于节点的函数。 l可能会返回节点的文本或锚点的href:

link = get_val(item,'.//a[contains(@class,"hdrlnk")]', lambda n: n.attrib["href"])
price = get_val(item,'.//span[@class="result-price"]', lambda n: n.text)

现在输出是:

...
https://bangalore.craigslist.co.in/reb/d/residential-plot-sarjapur/6522786441.html ₨1000
https://bangalore.craigslist.co.in/reb/d/prestige-dolce-vita/6522754197.html 
https://bangalore.craigslist.co.in/reb/d/brigade-golden-triangle/6522687904.html ₨12500000
https://bangalore.craigslist.co.in/reb/d/nikoo-homes/6522687772.html ₨6900000