它的嵌套比你想象的要深。这就是您收到错误消息的原因。
代码示例
import scrapy
import json
class MainSpider(scrapy.Spider):
name = 'test'
start_urls = ['https://experts.expcloud.com/api4/std?searchterms=AB&size=216&from=0']
def parse(self, response):
resp = json.loads(response.body)
values = resp['hits']['hits']
for value in values:
yield {
'Full Name': value['_source']['fullName'],
'Primary Phone':value['_source']['primaryPhone']
}
解释
resp 变量正在创建一个 python 字典,但这个 JSON 数据中没有 resp['hits']['hits']['fullName']。您正在寻找的数据,fullName 实际上是resp['hits']['hits'][i]['_source']['fullName']。 i 是一个数字,因为 resp['hits']['hits'] 是一个列表。
resp['hits'] 是一个字典,因此 values 变量很好。
但是resp['hits']['hits'] 是一个列表,因此您不能使用get 请求,它只接受数字作为[] 中的值,而不是字符串。因此出现错误。
提示
-
使用 response.json() 代替 json.loads(response.body),从 Scrapy v2.2 开始,scrapy 现在内部支持 json。在幕后它已经导入了 json。
-
还要检查 json 数据,我使用 requests 是为了方便,只是进行嵌套,直到我得到你需要的数据。
-
生成字典对于这种类型的数据来说很好,因为它的结构很好,但是任何其他需要修改或更改或某些地方错误的数据。使用 Items 字典或 ItemLoader。这两种产生输出的方式比产生字典要灵活得多。我几乎从不生成字典,唯一的时候是你拥有高度结构化的数据。
更新代码
查看 JSON 数据,有相当多的缺失数据。这是网络抓取的一部分,您会发现这样的错误。这里我们使用 try 和 except 块,因为当我们得到一个 KeyError 时,这意味着 python 无法识别与值关联的键。我们必须处理这个异常,我们在这里通过说产生一个字符串'No XXX'
一旦您开始发现差距等,最好考虑使用 Items 字典或 Itemloaders。
现在值得看看关于项目的 Scrapy 文档。本质上,Scrapy 做了两件事,它从网站中提取数据,并提供了一种存储这些数据的机制。它这样做的方式是将其存储在一个名为 Items 的字典中。代码与生成字典没有太大区别,但 Items 字典允许您更轻松地操作提取的数据,并使用 scrapy 可以做的额外事情。您需要先使用所需的字段编辑 items.py。我们创建一个名为 TestItem 的类,我们使用 scrapy.Field() 定义每个字段。然后我们可以在我们的蜘蛛脚本中导入这个类。
项目.py
import scrapy
class TestItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
full_name = scrapy.Field()
Phone = scrapy.Field()
Email = scrapy.Field()
City = scrapy.Field()
Zip_code = scrapy.Field()
Website = scrapy.Field()
Facebook = scrapy.Field()
Linkedin = scrapy.Field()
Twitter = scrapy.Field()
Bio = scrapy.Field()
这里我们指定了我们想要的字段,不幸的是你不能使用带空格的字符串,因此为什么全名是 full_name。 field() 为我们创建了 item 字典的字段。
我们使用from ..items import TestItem 将此项目字典导入我们的蜘蛛脚本。 from ..items 表示我们将 items.py 从父文件夹带到蜘蛛脚本,并且我们正在导入类 TestItem。这样我们的蜘蛛就可以用我们的 json 数据填充项目字典。
请注意,在 for 循环之前,我们通过 item = TestItem() 实例化 TestItem 类。实例化意味着调用类,在这种情况下它会创建一个字典。这意味着我们正在创建项目字典,然后我们用键和值填充该字典。从 for 循环中可以看到,您必须在添加键和值之前执行此操作。
蜘蛛脚本
import scrapy
import json
from ..items import TestItem
class MainSpider(scrapy.Spider):
name = 'test'
start_urls = ['https://experts.expcloud.com/api4/std?searchterms=AB&size=216&from=0']
def parse(self, response):
resp = json.loads(response.body)
values = response.json()['hits']['hits']
item = TestItem()
for value in values:
try:
item['full_name'] = value['_source']['fullName']
except KeyError:
item['full_name'] = 'No Name'
try:
item['Phone'] = value['_source']['primaryPhone']
except KeyError:
item['Phone'] = 'No Phone number'
try:
item["Email"] = value['_source']['primaryEmail']
except KeyError:
item['Email'] = 'No Email'
try:
item["City"] = value['_source']['activeLocations'][0]['city']
except KeyError:
item['City'] = 'No City'
try:
item["Zip_code"] = value['_source']['activeLocations'][0]['zipcode']
except KeyError:
item['Zip_code'] = 'No Zip code'
try:
item["Website"] = value['AgentMarketingCenter'][0]['Website']
except KeyError:
item['Website'] = 'No Website'
try:
item["Facebook"] = value['_source']['AgentMarketingCenter'][0]['Facebook_URL']
except KeyError:
item['Facebook'] = 'No Facebook'
try:
item["Linkedin"] = value['_source']['AgentMarketingCenter'][0]['LinkedIn_URL']
except KeyError:
item['Linkedin'] = 'No Linkedin'
try:
item["Twitter"] = value['_source']['AgentMarketingCenter'][0]['Twitter']
except KeyError:
item['Twitter'] = 'No Twitter'
try:
item["Bio"]: value['_source']['AgentMarketingCenter'][0]['Bio']
except KeyError:
item['Bio'] = 'No Bio'
yield item