我正在尝试使用django-rq在Python中创建网站抓取工具。到目前为止,我的工作人员看起来像这样:
status=1
。status=0
并将链接添加到队列。 status=1
表示页面已处理完毕。 status=0
表示该页面尚未处理。
现在,这个算法适用于单个工作者。但是,当有更多的工人因为工作常规的结束有时会被触发时,它就不会发生。
实施此工作人员的正确方法是什么?
答案 0 :(得分:3)
所以你的系统就像:
start job:
1. Create a page record in the database. Set status=0. Add page to queue.
worker:
1. Get the next page from the queue.
2. Download the page contents and process. Might take up to a minute or so.
3. For each link in the page
1. Check if the link is already registered in the database.
2. If not, create a new page record. Set status=0 and add the link to the queue.
4. After the for loop ends, set status=1 for this page.
5. Check whether the count of pages with status=0 is 0. If yes, the job is done.
如果在上一个网页抓取工作完成之前启动了后续网络抓取工作,您将只能完成工作'在最后一个结束时。
您可以在您的数据库页面记录中添加一个作业ID,并重新定义“完成工作”。就像count(status=0 and job-id=x) = 0
来自RQ docs:
当作业入队时,queue.enqueue()方法返回一个Job实例。 ...它有一个方便的结果访问属性,当作业尚未完成时将返回None,或者当作业完成时返回非None值(当然,假设作业首先有一个返回值)
您可以排队两种不同类型的作业,一种是“抓取网页”。另一个用于管理抓取过程。
管理工作将启动并跟踪所有提取网页'工作。它会知道什么时候完成工作'因为它的所有子工作都已完成。
您不一定 需要向数据库写入任何内容来管理抓取过程。
您需要运行2个以上的工作人员,以便crawl
和fetch
可以同时处理,可能在不同的队列中。
def something_web_facing():
...
queue.enqueue(crawl, 'http://url.com/start_point.html')
...
def crawl(start_url):
fetch_jobs = []
seen_urls = set()
seen_urls.add(start_url)
fetch_jobs.append( queue.enqueue(fetch, start_url) )
while len(fetch_jobs) > 0:
# loop over a copy of fetch_jobs
for job in list(fetch_jobs):
# has this job completed yet?
if job.result:
# a fetch job returns a list of the next urls to crawl
for url in job.result:
# fetch this url if we haven't seen it before
if url not in seen_urls:
seen_urls.add(url)
fetch_jobs.append( queue.enqueue(fetch, url) )
fetch_jobs.remove(job)
time.sleep(1)
return "Job done!"
def fetch(url):
"""Get web page from url, return a list of links to follow next"""
html_page = download_web_page(url)
links_to_follow = find_links_to_follow(html_page)
return links_to_follow
您可以排队使用scrapy的作业。 Run scrapy from a script
答案 1 :(得分:2)
只是一个想法,但你不能有一个额外的表来保存工人的状态吗?
即,有10名工人和以下国家: 0-8 - “持有” 9 - “工作”
从这个状态,9可能会在0-8可以处理的队列中添加更多页面(并将表中的状态更改为“正常工作”)。
另外需要注意的是,工人如何确定其状态的顺序需要准确:
如果一个工人处于等待状态,那么它的行动顺序可能类似于:
任何处于“保持”状态的工人都应定期检查是否有任何工人处于“工作”状态。如果是,请检查队列然后再睡觉。如果没有,请结束。
另一种方法是让一个命令和控制工作人员监视其他工作人员。如果他们都处于“保持”状态,则触发一个他们都注意结束的标志。