1.调整您当前的系统
- 如果您推迟将页面的状态设置为 1,直到您完成处理它,那么您的工作人员不应该提前宣布“工作完成”。
- 您的第 2 步仅对您开始抓取的第一个页面是必需的。
所以你的系统会是这样的:
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
2.利用RQ的工作类
来自RQ 文档:
当作业入队时, 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
3.使用别人的网络爬虫代码
刮擦
你可以排队使用scrapy的工作。从脚本运行scrapy