我想分析一些互联网站(例如有关科幻小说的网站)的链接结构和文字内容。 我有一份我想要删除的授权网站列表,其中大约有300个。一旦我在数据库中获得了已爬网页面,我将使用其他工具分析数据。
似乎Scrapy是执行此类任务的最佳工具之一,但我正在努力定义一个执行我需要的蜘蛛。我需要以下功能:
为了实现这一目标,我已经开始以这种方式定义蜘蛛:
# 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
如何在allow
中将允许的网站列表加载到Spider中?
要存储项目,我使用的管道似乎工作正常(它还没有时间逻辑,但它将数据存储在本地数据库中):
# 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
如果db已存在于db?
中,如何阻止蜘蛛请求URL?我采用了合理的方法,还是在Scrapy中有更自然的方法来做这些事情?我的Python不是很好,所以也欢迎编码建议: - )
感谢您的任何评论, Mulone
答案 0 :(得分:2)
所以,我意识到这是一个非常晚的答案,但这是我试图回答你的问题:
1)对于抓取txt文件中列出的域,您只需要在__init__
方法上填充spider属性allowed_domains
:
class PageSpider(CrawlSpider):
name = "page"
def __init__(self, *args, **kwargs):
self.allowed_domains = open('YOUR_FILE').read().splitlines()
super(PageSpider, self).__init__(*args, **kwargs)
2)要限制深度,只需设置DEPTH_LIMIT
setting。
3)要将数据保存在数据库中,管道是可行的方法 - 您正确地执行它。 =)
4)Scrapy已经通过deault避免了同一次抓取中的重复请求,但为了避免在之前的抓取中发出重复请求,您必须选择一种机制来存储外部先前抓取的请求并过滤{ {3}}就像Talvalin在评论中链接的那样:spider middleware