首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用刮痕从200 k域中提取文本

用刮痕从200 k域中提取文本
EN

Stack Overflow用户
提问于 2016-12-21 12:20:25
回答 1查看 1.2K关注 0票数 1

我的问题是:我想从某个域提取所有有价值的文本,例如www.example.com。所以我去这个网站,访问所有的链接与最大深度2,并编写它的csv文件。

我用scrapy编写了这个模块,它用一个进程解决了这个问题,并产生了多个爬虫器,但是效率很低--我能够抓取1k域/~5k网站/h,据我所知,我的瓶颈是CPU (因为GIL?)。离开电脑一段时间后,我发现我的网络连接断了。

当我想要使用多个进程时,我刚刚从并行过程中抓取蜘蛛的多处理中得到了错误:因此,这意味着我必须学习扭曲,如果与异步比较,我会说我不推荐它,但这只是我的观点。

所以我有几个主意要做

  • 反击,并尝试学习扭曲和实现多处理和使用Redis分布式队列,但我不认为刮擦是正确的工具,这类工作。
  • 使用pyspider -它有我需要的所有特性(我从未使用过)
  • 和纳奇一起去吧--这太复杂了(我从来没有用过)
  • 尝试构建我自己的分布式爬虫,但是在抓取了4个网站之后,我发现了4种边缘情况: SSL、复制、超时。但它将很容易添加一些修改,如:重点爬行。

你推荐什么解决方案?

Edit1:共享代码

代码语言:javascript
复制
class ESIndexingPipeline(object):
    def __init__(self):
        # self.text = set()
        self.extracted_type = []
        self.text = OrderedSet()
        import html2text
        self.h = html2text.HTML2Text()
        self.h.ignore_links = True
        self.h.images_to_alt = True

    def process_item(self, item, spider):
        body = item['body']
        body = self.h.handle(str(body, 'utf8')).split('\n')

        first_line = True
        for piece in body:
            piece = piece.strip(' \n\t\r')
            if len(piece) == 0:
                first_line = True
            else:
                e = ''
                if not self.text.empty() and not first_line and not regex.match(piece):
                    e = self.text.pop() + ' '
                e += piece
                self.text.add(e)
                first_line = False

        return item

    def open_spider(self, spider):
        self.target_id = spider.target_id
        self.queue = spider.queue

    def close_spider(self, spider):
        self.text = [e for e in self.text if comprehension_helper(langdetect.detect, e) == 'en']
        if spider.write_to_file:
            self._write_to_file(spider)

    def _write_to_file(self, spider):
        concat = "\n".join(self.text)
        self.queue.put([self.target_id, concat])

并呼吁:

代码语言:javascript
复制
def execute_crawler_process(targets, write_to_file=True, settings=None, parallel=800, queue=None):
    if settings is None:
        settings = DEFAULT_SPIDER_SETTINGS

    # causes that runners work sequentially
    @defer.inlineCallbacks
    def crawl(runner):
        n_crawlers_batch = 0
        done = 0
        n = float(len(targets))
        for url in targets:
            #print("target: ", url)
            n_crawlers_batch += 1
            r = runner.crawl(
                TextExtractionSpider,
                url=url,
                target_id=url,
                write_to_file=write_to_file,
                queue=queue)
            if n_crawlers_batch == parallel:
                print('joining')
                n_crawlers_batch = 0
                d = runner.join()
                # todo: print before yield
                done += n_crawlers_batch
                yield d  # download rest of data
        if n_crawlers_batch < parallel:
            d = runner.join()
            done += n_crawlers_batch
            yield d

        reactor.stop()

    def f():
        runner = CrawlerProcess(settings)
        crawl(runner)
        reactor.run()

    p = Process(target=f)
    p.start()

蜘蛛不是特别有趣。

EN

回答 1

Stack Overflow用户

发布于 2016-12-21 14:41:47

您可以使用刮刮-雷迪斯。它基本上是一种爬行器,它从Redis中的队列中获取URL来爬行。优点是您可以启动许多并发的蜘蛛,这样就可以更快地爬行。爬行器的所有实例都将从队列中提取URL,并在URL用完时等待空闲进行爬行。Scrapy的存储库提供了一个实现此功能的示例项目。

我使用scrape触发64个我的爬虫实例,在大约1小时内刮取100万个URL。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41262701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档