Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用刮泥机刮取大量站点_Python_Web Scraping_Scrapy - Fatal编程技术网

Python 用刮泥机刮取大量站点

Python 用刮泥机刮取大量站点,python,web-scraping,scrapy,Python,Web Scraping,Scrapy,我想分析一些相互连接的网站(例如关于科幻小说的网站)的链接结构和文本内容。 我有一个授权网站的名单,我想刮,其中约300个。一旦我有了数据库中的爬网页面,我将用其他工具分析数据 似乎Scrapy是执行此类任务的最佳工具之一,但我正在努力定义一个能够执行我需要的任务的spider。我需要以下功能: 仅刮取某些域(在可能更改的外部文本文件中定义的列表) 将递归深度限制为给定值(例如3) 对于每个页面,将标题、html内容和链接保存在sql lite数据库中 使用缓存避免重击网站以下载相同的页面。缓

我想分析一些相互连接的网站(例如关于科幻小说的网站)的链接结构和文本内容。 我有一个授权网站的名单,我想刮,其中约300个。一旦我有了数据库中的爬网页面,我将用其他工具分析数据

似乎Scrapy是执行此类任务的最佳工具之一,但我正在努力定义一个能够执行我需要的任务的spider。我需要以下功能:

  • 仅刮取某些域(在可能更改的外部文本文件中定义的列表)
  • 将递归深度限制为给定值(例如3)
  • 对于每个页面,将标题、html内容和链接保存在sql lite数据库中
  • 使用缓存避免重击网站以下载相同的页面。缓存应具有到期日期(例如1周)。到期日后,应再次刮掉该页
  • 我想手动运行spider(目前我不需要调度)
为了实现这一目标,我开始用以下方式定义spider:

# 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中? 为了存储项目,我使用了一个管道,它似乎工作正常(它还没有时态逻辑,但它将数据存储在本地数据库中):

如果数据库中已经存在URL,如何阻止爬行器请求URL

我是采取了明智的方法,还是有更自然的方法来做这些事情?我的Python不是很好,因此也欢迎您提出编码建议:-)

谢谢你的评论,
Mulone

因此,我意识到这是一个非常晚的答案,但以下是我试图回答您的问题:

1) 对于txt文件中列出的抓取域,您只需要在
\uuuuu init\uuuu
方法中填充spider属性:

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) 要限制深度,只需设置

3) 要将数据保存到数据库中,管道是一种方法——您做得对


4) Scrapy已经在deault的相同爬网中避免了重复请求,但为了避免在以前的爬网中重复请求,您必须选择一种机制来从外部存储来自以前爬网的请求,并以类似Talvalin在评论中链接的方式进行过滤:

我认为在请求实际发出之前,使用downloader中间件过滤重复的URL通常更好。看看这个问题,了解如何实现这一点的更多细节:对于缓存,在scrapy中有一个设置
class PageSpider(CrawlSpider):
    name = "page"
    def __init__(self, *args, **kwargs):
        self.allowed_domains = open('YOUR_FILE').read().splitlines()
        super(PageSpider, self).__init__(*args, **kwargs)