我希望分析一些相互连接的网站(例如关于科幻小说的网站)的链接结构和文本内容。我有一个授权网站列表,约有300个,我想进行爬取。当我在数据库中拥有了抓取到的页面后,将使用其他工具对数据进行分析。
似乎Scrapy是执行这种任务的最佳工具之一,但我难以定义一个执行我所需功能的蜘蛛程序。我需要以下功能:
- 仅爬取特定域名(列表在外部文本文件中定义,可能会更改)。 - 将递归深度限制为给定值(例如3)。 - 对于每个页面,保存标题、HTML内容和链接到SQL Lite DB。 - 使用缓存避免下载相同页面的负载。缓存应具有过期日期(例如1周)。过期后,应重新爬取页面。 - 我想手动运行蜘蛛程序(目前不需要计划)。
为了实现这个目标,我已经开始这样定义一个蜘蛛程序:
我该如何将允许的网站列表加载到Spider中的“allow”中呢? 为了存储这些项目,我使用了一个管道,似乎工作得不错(它还没有时间逻辑,但它可以将数据存储在本地数据库中):
我该如何阻止蜘蛛请求已经在数据库中存在的URL?
在Scrapy中,我所采用的方法是否明智?如果有更自然的方法,请告知。由于我的Python水平不是很高,所以编程建议也将受欢迎 :-)
感谢您的任何意见, Mulone
似乎Scrapy是执行这种任务的最佳工具之一,但我难以定义一个执行我所需功能的蜘蛛程序。我需要以下功能:
- 仅爬取特定域名(列表在外部文本文件中定义,可能会更改)。 - 将递归深度限制为给定值(例如3)。 - 对于每个页面,保存标题、HTML内容和链接到SQL Lite DB。 - 使用缓存避免下载相同页面的负载。缓存应具有过期日期(例如1周)。过期后,应重新爬取页面。 - 我想手动运行蜘蛛程序(目前不需要计划)。
为了实现这个目标,我已经开始这样定义一个蜘蛛程序:
# http://doc.scrapy.org/en/latest/intro/tutorial.html
from scrapy.spider import Spider
from scrapy import log
from scrapy.http.request import Request
from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import HtmlXPathSelector
from scrapy.selector import Selector
from ..items import PageItem
class PageSpider(CrawlSpider):
name = "page"
rules = (Rule(SgmlLinkExtractor(allow=(),), callback='parse_item', follow=True),)
#restrict_xpaths=('//body',)),
def parse_item(self, response):
log.msg( "PageSpider.parse" )
log.msg( response.url )
#sel = Selector(response)
links = sel.xpath('//body//a/@href').extract()
#log.msg("links")
#log.msg(links)
item = PageItem()
item['url'] = response.url
item['content'] = response.body
item['links'] = "\n".join( links )
return item
我该如何将允许的网站列表加载到Spider中的“allow”中呢? 为了存储这些项目,我使用了一个管道,似乎工作得不错(它还没有时间逻辑,但它可以将数据存储在本地数据库中):
# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html
from scrapy import log
import sqlite3
import time
#from items import PageItem
class MyProjectPipeline(object):
_db_conn = None;
def process_item(self, item, spider):
log.msg( "process item" )
if not self.url_exists(item['url']):
# insert element
c = MyProjectPipeline._db_conn.cursor()
items = [( item['url'], item['content'], item['links'], time.time() )]
c.executemany('INSERT INTO pages_dump VALUES (?,?,?,?)', items)
MyProjectPipeline._db_conn.commit()
return item
def open_spider(self, spider):
# https://docs.python.org/2/library/sqlite3.html
log.msg( "open sql lite DB" )
MyProjectPipeline._db_conn = sqlite3.connect('consp_crawl_pages.db')
c = MyProjectPipeline._db_conn.cursor()
# create table
c.execute('''create table if not exists pages_dump ( p_url PRIMARY KEY, p_content, p_links, p_ts )''')
MyProjectPipeline._db_conn.commit()
def close_spider(self, spider):
log.msg( "closing sql lite DB" )
MyProjectPipeline._db_conn.close()
def url_exists(self, url):
c = MyProjectPipeline._db_conn.cursor()
c.execute("SELECT p_url FROM pages_dump WHERE p_url = ?", (url,))
data=c.fetchone()
if data is None:
return False
return True
我该如何阻止蜘蛛请求已经在数据库中存在的URL?
在Scrapy中,我所采用的方法是否明智?如果有更自然的方法,请告知。由于我的Python水平不是很高,所以编程建议也将受欢迎 :-)
感谢您的任何意见, Mulone