展望の説明:
APPは、国家の注文を取得し、単一のボリュームを取得する必要があります。ノー国が順番に通過する各都市の個別の唯一のオプションができるからです。爬虫類はアクションなしで、更新された強盗の受注があり、データベースからの最後のデータが比較され、削除、一度48時間以内に注文を取得し、一日一回実行します。(ここでの更新ロジックが重要ではなく、重要なのは、ロジックをクロールしています)。各注文リリースタイムを持っている、公開された裁判官によると、48時間営業の停止クロールの外に、街を取り除くには、登り始めました。
初版を見てください:
#spider
# 构造一些请求参数,此处省略
# 从配置中读取所有城市列表
cities = self.settings['CITY_CH']
# end_signal为某个城市爬取完毕的信号,
self.end_signal = False
for city in cities:
# 通过for循环对每个城市进行订单爬取
post_data.update({'locationName':city})
count = 1
while not self.end_signas:
post_data.update({'pageNum':str(count)})
data = ''.join(json.dumps(post_data, ensure_ascii=False).split())
sign = MD5Util.hex_digest(api_key + data + salt).upper()
params = {
'apiKey':api_key,
'data':data,
'system':system,
'sign':sign
}
meta = {'page':count}
yield scrapy.Request(url=url, method='POST', body=json.dumps(params, ensure_ascii=False),
headers=self.headers, callback=self.parse,meta=meta, dont_filter=True)
count+=1
self.end_signal = False
def parse(self,response):
# 略
# 在spiderMiddleware中根据返回的item中的订单时间进行判断(此处不详写)
def process_spider_output(self, response, result, spider):
result_bkp = []
for res in result:
if res['order_time'] < before_date(2): #before_date为自定义的时间函数
logger.info("{%s}爬取完毕,开始爬取下一个城市" % (res['city_name']))
spider.end_signal = True
break
result_bkp.append(res.copy())
return result_bkp
一見何の問題以上に設定されている48時間以上か否かを判断するためには、spiderMiddlewareに戻り項目の後に解決解決するには、各都市を通して、ありません
self.end_signal为True
クモでwhileループの外に、このパラメータが設定されているwhileループのターンの裏に注意を払うFalse
その後、街の次のサイクルが始まりました。
質問です:
意志のクモの要求は、キューに追加して戻すためにキューがあるバックparse関数の良好なリターンをダウンロードすることにより、応答時間もたまに少しネットワークに遭遇するよく知られた不運の人々のキューに対処しなければならないとき、明確な栗与えるために質問、
栗:クモに都市A、2、3受注ページ(2、3は、注文ページの48時間以上である)、キューに追加可能ダウンロードするダウンローダ最初2つの、3ページ目に48時間以上のリンク・エージェント、ミドルウェアが正常に設定を決定するself.end_signal=True
次の都市のクロールを。市Bは、(48時間以内にすべての)1,2,3を追加し、この時間は、ダウンロード中の都市裁判官の順序の2ページ目には完全なミドルウェアターンであるself.end_signal=True
ので、Bの受注の背後にある都市もなくなって、すべてのこれ以上。。。直接都市の命令の下に開始!
要約バージョン:
プログラム全体の制御フローを非同期プログラムでグローバル変数を移動しないでください。(悪い要約、あなたは私をまとめることができます)
第二版:
それが終わった順クロールを示すために、ロゴとすべての都市を作ることができるグローバル変数によって制御することができないので。
コードを見てください
#spider
cities = self.settings['CITY_CH']
# end_signal为某个城市爬取完毕的信号,
self.end_signal = False
for city in cities:
# 通过for循环对每个城市进行订单爬取
post_data.update({'locationName':city})
count = 1
print(cities)
print(city)
while in cities:
post_data.update({'pageNum':str(count)})
data = ''.join(json.dumps(post_data, ensure_ascii=False).split())
sign = MD5Util.hex_digest(api_key + data + salt).upper()
params = {
'apiKey':api_key,
'data':data,
'system':system,
'sign':sign
}
meta = {'page':count}
yield scrapy.Request(url=url, method='POST', body=json.dumps(params, ensure_ascii=False),
headers=self.headers, callback=self.parse,meta=meta, dont_filter=True)
count+=1
self.end_signal = False
def parse(self,response):
# 略
# 在spiderMiddleware中根据返回的item中的订单时间进行判断(此处不详写)
def process_spider_output(self, response, result, spider):
result_bkp = []
for res in result:
if res['order_time'] < before_date(2): #before_date为自定义的时间函数
if res['city_name'] in spider.cities:
spider.cities.remove(res['city_name'])
logger.info("{%s}爬取完毕,开始爬取下一个城市" % (res['city_name']))
break
result_bkp.append(res.copy())
return result_bkp
リストの中の都市かどうかを判断するためのロジックを意味するビットにも参照してください、説明の言葉でこの街を削除し終えクロール、クロールを完了していません。ああ!最後までやれ!
興味深いことに最初の都市は、通常のクロール、来る、第二の都市は消えていた、(3つの都市にあります)、それが飲み込まれたか、最後に直接ジャンプするために、第2の都市が表示されない印刷された都市コードの魅力。
機密性の高いデータは、スクリーンショットではありません。
印刷は、明らかにそこが削除されていない、なぜ街直接の最後に北京で都市のリストを見ることができますか?
それを見た兄があったかもしれない、私はしてもループのバグの内側にあるものを疑い、長い時間のために命とデバッグポイントによって中断されました。
最後に、アイデア(面白い)、問題は都市のリストであるため、困惑?Iそれを循環させるために、それは、要素内に行くために彼の中でそれをすることができます削除しますか?
デモテストを書きます
cities = ['鞍山', '北京', '昆玉',]
for city in cities:
cities.remove('鞍山')
print(city)
# 错误就来了! 果然不能在循环它的时候再对它进行删除操作
ValueError: list.remove(x): x not in list
このエラーは、実行scrapyで報告されていない理由としては、それは例外処理を行ってどこか別の場所かもしれないが、この問題があり、我々はそれを少し修正して行きます。
ウィルfor city in cities
変更することはfor city in cities.copy()
、完璧なソリューションを!!!
注意を払うようにアイテムを扱うときに小さなPythonのポイントは、配信および配信アドレスの値でもあります。