【发布时间】:2015-05-07 05:26:26
【问题描述】:
我一直想知道使用 scrapy 废弃多级数据的最佳方法是什么 我将分四个阶段描述情况,
- 我为抓取这些数据而遵循的当前架构
- 基本代码结构
- 困难以及为什么我认为必须有更好的选择
- 我尝试存储数据并失败然后部分成功的格式
当前架构
- 数据结构
首页:艺术家名单
第二页:每个艺术家的专辑列表
第三页:每张专辑的歌曲列表
- 基本代码结构
类 MusicLibrary(蜘蛛): name = '音乐库'
def parse(self, response):
items = Discography()
items['artists'] = []
for artist in artists:
item = Artist()
item['albums'] = []
item['artist_name'] = "name"
items['artists'].append(item)
album_page_url = "extract link to album and yield that page"
yield Request(album_page_url,
callback=self.parse_album,
meta={'item': items,
'artist_name': item['artist_name']})
def parse_album(self, response):
base_item = response.meta['item']
artist_name = response.meta['artist_name']
# this will search for the artist added in previous method and append album under that artist
artist_index = self.get_artist_index(base_item['artists'], artist_name)
albums = "some path selector"
for album in albums:
item = Album()
item['songs'] = []
item['album_name'] = "name"
base_item['artists'][artist_index]['albums'].append(item)
song_page_url = "extract link to song and yield that page"
yield Request(song_page_url,
callback=self.parse_song_name,
meta={'item': base_item,
"key": item['album_name'],
'artist_index': artist_index})
def parse_song_name(self, response):
base_item = response.meta['item']
album_name = response.meta['key']
artist_index = response.meta["artist_index"]
album_index = self.search(base_item['artists'][artist_index]['albums'], album_name)
songs = "some path selector "
for song in songs:
item = Song()
song_name = "song name"
base_item['artists'][artist_index]['albums'][album_index]['songs'].append(item)
# total_count (total songs to parse) = Main Artist page is having the list of total songs for each artist
# current_count(currently parsed) = i will go to each artist->album->songs->[] and count the length
# i will yield the base_item only when songs to scrape and song scraped count matches
if current_count == total_count:
yield base_item
-
困难以及为什么我认为必须有更好的选择
- 目前我只在所有页面和子页面都被抓取时才产生项目对象,条件是要抓取的歌曲和抓取的歌曲计数匹配..
- 但是给出抓取的性质和抓取的数量......有些页面要给我除 (200-status ok) 之外的代码,这些歌曲不会被抓取,项目计数也不匹配
- 所以最后,即使 90% 的页面将被成功抓取并且计数不匹配,也不会产生任何结果,并且所有 CPU 功率都将丢失..
-
我尝试存储数据并失败然后部分成功的格式
- 我想要单行格式的每个项目对象的数据 即艺术家名-专辑名-歌曲名 因此,如果艺术家 A 有 1 张专辑 (aa),其中包含 8 首歌曲 ... 8 个商品将存储,每首歌曲有一个条目 (item)
- 但是对于当前格式,当我尝试在最后一个函数“parse_song_name”中每次都产生时,它每次都会产生复杂的结构,并且对象每次都是递增的......
- 然后我认为在第一个 Discography->artist 然后是 Artist->albums 然后是 Albums->songs 中附加所有内容是问题所在,但是当我删除附加并尝试不这样做时,我只产生了一个对象,即最后一个不是全部..
- 所以最后,如前所述开发了这个工作,但它不是每次都工作(在没有 200 状态代码的情况下)
- 当它工作时,在屈服之后,我编写了一个管道,在其中我再次解析这个 JSON 并将其存储为我最初想要的数据格式(每首歌曲一行 --flat 结构)
谁能建议我在这里做错了什么,或者当某些页面返回非 200 代码时,我该如何提高效率并使其正常工作?
【问题讨论】:
-
能否请您发布开始网址?
-
如果可能,请也发布输出 json 格式?如果您可以发布 start-url 那就太好了,因为有时对 url 进行一些简单的调整可以减少额外的代码行以及请求。
-
我从失败的代码版本重新开始,其中所有项目对象都具有相同的专辑和艺术家名称但歌曲名称不同......问题是可变对象......项目列表/字典是可变对象,每个回调方法都在接收同一个对象,并且所有迭代都在更改同一个对象....
-
所以我的解决方案是使用 copy.deepcopy 在每个回调函数中创建新的项目对象并生成该新对象,而保持该基础引用不变..
标签: python selenium data-structures web-crawler scrapy