【发布时间】:2017-01-05 04:01:57
【问题描述】:
我现在的练习:
每次刷新或加载页面时,我让我的后端捕获前端页面发送的 get 请求 来运行我的 scrapy 蜘蛛。抓取的数据将显示在我的首页。这是代码,我调用了一个子进程来运行蜘蛛:
from subprocess import run
@get('/api/get_presentcode')
def api_get_presentcode():
if os.path.exists("/static/presentcodes.json"):
run("rm presentcodes.json", shell=True)
run("scrapy crawl presentcodespider -o ../static/presentcodes.json", shell=True, cwd="./presentcodeSpider")
with open("/static/presentcodes.json") as data_file:
data = json.load(data_file)
logging.info(data)
return data
效果很好。
我想要什么:
但是,蜘蛛抓取的网站几乎没有变化,因此不需要经常抓取。
所以我想在后端使用 coroutine 方法每 30 分钟运行一次我的 scrapy spider。
我尝试并成功的方法:
from subprocess import run
# init of my web application
async def init(loop):
....
async def run_spider():
while True:
print("Run spider...")
await asyncio.sleep(10) # to check results more obviously
loop = asyncio.get_event_loop()
tasks = [run_spider(), init(loop)]
loop.run_until_complete(asyncio.wait(tasks))
loop.run_forever()
它也很好用。
但是当我把run_spider()的代码改成这个时(和第一个基本一样):
async def run_spider():
while True:
if os.path.exists("/static/presentcodes.json"):
run("rm presentcodes.json", shell=True)
run("scrapy crawl presentcodespider -o ../static/presentcodes.json", shell=True, cwd="./presentcodeSpider")
await asyncio.sleep(20)
蜘蛛只在第一次运行,爬取的数据成功存储到presentcode.json,但20秒后蜘蛛就再也没有调用过。
问题
我的程序出了什么问题?是不是因为我在协程中调用了子进程而无效?
在主应用程序运行时运行蜘蛛有什么更好的想法吗?
编辑:
我先把我的网络应用初始化函数的代码放在这里:
async def init(loop):
logging.info("App started at {0}".format(datetime.now()))
await orm.create_pool(loop=loop, user='root', password='', db='myBlog')
app = web.Application(loop=loop, middlewares=[
logger_factory, auth_factory, response_factory
])
init_jinja2(app, filters=dict(datetime=datetime_filter))
add_routes(app, 'handlers')
add_static(app)
srv = await loop.create_server(app.make_handler(), '127.0.0.1', 9000) # It seems something happened here.
logging.info('server started at http://127.0.0.1:9000') # this log didn't show up.
return srv
我的想法是,主应用程序使协程事件循环“卡住”,因此蜘蛛以后无法回调。
让我看看create_server和run_until_complete的源码..
【问题讨论】:
-
这是一个 Python/异步问题。不是一个乱七八糟的 :) 在原则上,不要做
rm然后scrapy crawl因为那样您将有一段时间没有文件并且您的请求将失败。首先将scrapy crawl写入临时文件,例如/static/presentcodes.json.tmp然后做一个mv /static/presentcodes.json.tmp /static/presentcodes.json这是 atomic-ish -
@neverlastn 你的意思是哪个 request 会失败? REST 从网页获取请求?实际上,我现在没有使用 request,我只是让 main web application 和 spider 同时运行。前端页面的文件读取和数据显示将在稍后考虑,现在它们都被“注释”了。无论如何,我会先尝试您的解决方案,谢谢!
-
没错,你是对的!现在没有任何问题,但是使用
rm+crawl,一旦您尝试对该文件执行任何操作(除非您有相对复杂的同步),您就会有不可用的时刻
标签: python subprocess python-asyncio coroutine