【发布时间】:2014-01-25 06:47:06
【问题描述】:
我的scrapy项目从列表页面“向下钻取”,检索不同级别的所列项目的数据,最高可达数个深度。可能有许多页面列出的项目,每个页面上都有少数不同的项目/链接。我正在从以下位置收集每个项目的详细信息(并将它们存储在单个 CSV Excel 文件中):它列出的页面、该列表中的页面链接(“更多详细信息”页面)以及另一个页面 -比方说,物品制造商的原始清单。
因为我正在构建一个 CSV 文件,所以在我的解析过程移动到下一个项目之前将每个项目的数据放在一行上会非常有帮助。如果只有在我在它出现的列表页面上为该项目编写 CSV 行时,我能得到一个启动请求,我就可以做得很好。如果需要,我会根据需要为每个级别使用不同的解析函数“向下钻取”尽可能多的级别,并一直使用单个项目,直到我拥有它需要的整个 CSV 文件行。
看起来我将不得不为每个级别的每个项目重新编写 CSV 文件,而不是那么容易,因为我无法获取项目的“更多详细信息”链接响应直到我退出项目列表页面的整个解析功能,因此我的 CSV 文件的末尾不再是正在处理的项目,我必须在每一行上都有一个唯一的字段来查找每个项目在每个级别,重写文件等。
明白,我不知道哪个回调级别将是任何特定项目的最后一个回调级别。这是逐项确定的。有些项目甚至没有“更深”的级别。我剩下的唯一想法是只有一个递归回调函数来处理所有回调级别,但是这种事情是由你们其他人完成的,还是scrapy有一些“请求并等待响应”的方法或相似的东西?我不想在笔记本电脑上安装 sql 数据库,以前从未设置过。
谢谢!!!
from scrapy.spider import Spider
from scrapy.selector import Selector
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.exporter import CsvItemExporter
import csv
from meow.items import meowItem, meowPage
from scrapy.http import Request
import os
from mmap import mmap
class meowlistpage(Spider):
name="melist"
prefixhref='http://www.meow.com'
#add '2_p/', '3_p/', or '4_p/', etc. to get to meow's other pages
start_urls = [prefixhref+"/homes/for_sale/CO/house,mobile,land_type/10_rid/3000-30000_price/11-117_mp/800000-8000000_lot/lot_sort/46.377254,-96.82251,30.845647,-114.312744_rect/5_zm/1_p/1_rs/"]
print 'Retrieving first page...'
def parse(self, response):
print 'First page retrieved'
name="melist";prefixhref='http://www.meow.com';
csvfilename = 'C:\\Python27\\My scripts\\meow\\'+name+'.csv';csvfile = open(csvfilename, 'w');pass;csvfile.close()
hxs = Selector(response)
page_tags=hxs.xpath("//div[@id='search-results']/article")
for page_tags in page_tags:
item = meowItem()
item['ad_link']=prefixhref+str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/@href").extract())[3:-2]
idendplace=str(item['ad_link']).index('_zpid')-12; backhashstr=str(item['ad_link'])[idendplace:];
idstartplace=backhashstr.index('/')+1; idendplace=len(backhashstr)-backhashstr.index('_zpid');
item['zpid']=str(backhashstr)[idstartplace:-idendplace]
item['sale_sold']=str(page_tags.xpath(".//div[1]/dl[1]/dt[1]/@class").extract())[8:-17]#"recentlySold" or "forSale"
item['prop_price']=str(page_tags.xpath(".//div[1]/dl[1]/dt[2]/strong/text()").extract())[3:-2]
if (str(item['sale_sold'])=='recentlySold'):item['prop_price']=str(item['prop_price'])+str(page_tags.xpath(".//div[1]/dl[1]/dt[1]/strong/text()").extract())[3:-2]
try:
dollrsgn=item['prop_price'].index('$');item['prop_price']=str(item['prop_price'])[dollrsgn:]
except:pass
item['ad_title']=str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/@title").extract())[3:-2]
prop_latitude1=page_tags.xpath("@latitude").extract();item['prop_latitude']=str(prop_latitude1)[3:-8]+'.'+str(prop_latitude1)[5:-2]
prop_longitude1=page_tags.xpath("@longitude").extract();item['prop_longitude']=str(prop_longitude1)[3:-8]+'.'+str(prop_longitude1)[7:-2]
item['prop_address']=str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/span[1]/text()").extract())[3:-2]+', '+str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/span[2]/text()").extract())[3:-2]+', '+str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/span[3]/text()").extract())[3:-2]+' '+str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/span[4]/text()").extract())[3:-2]
mightmentionacres = str(page_tags.xpath(".//div[1]/dl[2]/dt[2]/text()").extract())[3:-2]+' | '+str(page_tags.xpath(".//div[1]/dl[2]/dt[2]/text()").extract())[3:-2]+' | '+str(page_tags.xpath(".//div[1]/dl[2]/dt[1]/span[1]/span[1]/a/@title").extract())[3:-2]+' | '#+str()[3:-2]#this last segment comes from full ad
item['prop_acres'] = mightmentionacres
#Here is where I'm talking about
yield Request(str(item['ad_link']), meta={'csvfilename':csvfilename, 'item':item}, dont_filter=True, callback = self.getthispage)
#By this point, I wanted all the callback[s] to have had executed, but they don't - Scrapy waits to launch them until after this function completes
csvfile = open(csvfilename, 'ab')
outwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
outwriter.writerow(item['zpid'], [item['sale_sold'], item['prop_price'], item['ad_title'],
item['prop_address'], item['prop_latitude'],
item['prop_longitude'], item['prop_acres'],
item['ad_link'], item['parcelnum'], item['lot_width']])
csvfile.close()
#retrieve href of next page of ads
next_results_pg=1
page_tags=hxs.xpath("//div[@id='list-container']/div[@id='search-pagination-wrapper-2']/ul[1]")
while (str(page_tags.xpath(".//li["+str(next_results_pg)+"]/@class").extract())[3:-2]!='current'):
next_results_pg+=1;
if (next_results_pg>80):
break
next_results_pg+=1#;item['next_results_pg'] = next_results_pg
if (str(page_tags.xpath(".//li["+str(next_results_pg)+"]/@class").extract())[3:-2]=='next'):return
next_results_pg_href = prefixhref+str(page_tags.xpath(".//li["+str(next_results_pg)+"]/a/@href").extract())[3:-2]#
if (next_results_pg_href != prefixhref):#need to also avoid launching pages otherwise not desired
page = meowPage()
page['next_results_pg_href'] = next_results_pg_href
print 'Retrieving page '+ next_results_pg_href
# yield Request(next_results_pg_href, dont_filter=True, callback = self.parse)
return
# if (item['next_results_pg_href']==prefixhref):
# print 'No results pages found after this one, next+results_pg='+str(next_results_pg)
# else:
# print 'Next page to parse after this one is '+str(item['next_results_pg_href'])
def getthispage(self, response):
#Even though the yield statement was used,
#nothing here really gets executed until
#until the first parse function resumes and
#then finishes completely.
return
【问题讨论】:
-
我不清楚您要做什么。 Scrapy CSV 导出器将序列化项目写入文件。如果您的项目需要多个请求才能完成,您可以在请求的元字典中传递不完整的项目,并在添加最后信息位的回调中返回完成的项目。您能否分享一些您正在使用的蜘蛛代码,以便我们提供更好的建议?
-
我会尝试这个以及我得到的一两个想法。让我们考虑一下这个答案。谢谢保罗。
-
meta dict 的想法失败了,原因如下:"yield Request(url,..." 允许程序执行过早返回。也就是说,yield 语句后面的语句先执行回调函数能够处理请求的响应。实际上只是改写我原来的问题。我确实意识到我可以写下所有的填写
-
不知何故我被切断了。无论如何,我可以长期这样做,并在找到临时文件时将数据项写入临时文件,然后在删除文件末尾不需要的 cr/lf 后连接文件,等等。我只是想在我的笔记本电脑上安装一个 sql 数据库,以前从未设置过。所以我还在为此苦苦挣扎。我不想发布网站名称的代码 b/c 以及删除它们所需要的所有麻烦,但我现在会努力做到这一点。
-
你把
meta的想法弄错了,使用它你不会产生一个项目,你向请求中添加一些值,这些值也会出现在响应中,meta是正确的方法在你的情况下
标签: python csv web-crawler scrapy