如何整合 Flask 和 Scrapy?

2023-11-26

我正在使用 scrapy 来获取数据,我想使用 Flask Web 框架在网页中显示结果。但我不知道如何调用烧瓶应用程序中的蜘蛛。我尝试过使用CrawlerProcess呼叫我的蜘蛛,但我收到这样的错误:

ValueError
ValueError: signal only works in main thread

Traceback (most recent call last)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Library/Python/2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Library/Python/2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Library/Python/2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/Rabbit/PycharmProjects/Flask_template/FlaskTemplate.py", line 102, in index
process = CrawlerProcess()
File "/Library/Python/2.7/site-packages/scrapy/crawler.py", line 210, in __init__
install_shutdown_handlers(self._signal_shutdown)
File "/Library/Python/2.7/site-packages/scrapy/utils/ossignal.py", line 21, in install_shutdown_handlers
reactor._handleSignals()
File "/Library/Python/2.7/site-packages/twisted/internet/posixbase.py", line 295, in _handleSignals
_SignalReactorMixin._handleSignals(self)
File "/Library/Python/2.7/site-packages/twisted/internet/base.py", line 1154, in _handleSignals
signal.signal(signal.SIGINT, self.sigInt)
ValueError: signal only works in main thread

我的scrapy代码是这样的:

class EPGD(Item):

genID = Field()
genID_url = Field()
taxID = Field()
taxID_url = Field()
familyID = Field()
familyID_url = Field()
chromosome = Field()
symbol = Field()
description = Field()

class EPGD_spider(Spider):
    name = "EPGD"
    allowed_domains = ["epgd.biosino.org"]
    term = "man"
    start_urls = ["http://epgd.biosino.org/EPGD/search/textsearch.jsp?textquery="+term+"&submit=Feeling+Lucky"]

db = DB_Con()
collection = db.getcollection(name, term)

def parse(self, response):
    sel = Selector(response)
    sites = sel.xpath('//tr[@class="odd"]|//tr[@class="even"]')
    url_list = []
    base_url = "http://epgd.biosino.org/EPGD"

    for site in sites:
        item = EPGD()
        item['genID'] = map(unicode.strip, site.xpath('td[1]/a/text()').extract())
        item['genID_url'] = base_url+map(unicode.strip, site.xpath('td[1]/a/@href').extract())[0][2:]
        item['taxID'] = map(unicode.strip, site.xpath('td[2]/a/text()').extract())
        item['taxID_url'] = map(unicode.strip, site.xpath('td[2]/a/@href').extract())
        item['familyID'] = map(unicode.strip, site.xpath('td[3]/a/text()').extract())
        item['familyID_url'] = base_url+map(unicode.strip, site.xpath('td[3]/a/@href').extract())[0][2:]
        item['chromosome'] = map(unicode.strip, site.xpath('td[4]/text()').extract())
        item['symbol'] = map(unicode.strip, site.xpath('td[5]/text()').extract())
        item['description'] = map(unicode.strip, site.xpath('td[6]/text()').extract())
        self.collection.update({"genID":item['genID']}, dict(item),  upsert=True)
        yield item

    sel_tmp = Selector(response)
    link = sel_tmp.xpath('//span[@id="quickPage"]')

    for site in link:
        url_list.append(site.xpath('a/@href').extract())

    for i in range(len(url_list[0])):
        if cmp(url_list[0][i], "#") == 0:
            if i+1 < len(url_list[0]):
                print url_list[0][i+1]
                actual_url = "http://epgd.biosino.org/EPGD/search/" + url_list[0][i+1]
                yield Request(actual_url, callback=self.parse)
                break
            else:
                print "The index is out of range!"

我的烧瓶代码是这样的:

@app.route('/', methods=['GET', 'POST'])
def index():
    process = CrawlerProcess()
    process.crawl(EPGD_spider)
    return redirect(url_for('details'))


@app.route('/details', methods = ['GET'])
def epgd():
    if request.method == 'GET':
        results = db['EPGD_test'].find()
        json_results= []
        for result in results:
            json_results.append(result)
        return toJson(json_results)

使用 Flask Web 框架时如何调用我的 scrapy 蜘蛛?


在蜘蛛前面添加 HTTP 服务器并不是那么容易。有几个选择。

1.Python子进程

如果您确实仅限于 Flask,如果您不能使用其他任何东西,那么将 Scrapy 与 Flask 集成的唯一方法是按照其他答案的建议为每个蜘蛛爬行启动外部进程(请注意,您的子进程需要在正确的 Scrapy 项目中生成)目录)。

所有示例的目录结构应该如下所示,我正在使用dirbot测试项目

> tree -L 1                                                                                                                                                              

├── dirbot
├── README.rst
├── scrapy.cfg
├── server.py
└── setup.py

以下是在新进程中启动 Scrapy 的代码示例:

# server.py
import subprocess

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    """
    Run spider in another process and store items in file. Simply issue command:

    > scrapy crawl dmoz -o "output.json"

    wait for  this command to finish, and read output.json to client.
    """
    spider_name = "dmoz"
    subprocess.check_output(['scrapy', 'crawl', spider_name, "-o", "output.json"])
    with open("output.json") as items_file:
        return items_file.read()

if __name__ == '__main__':
    app.run(debug=True)

将上面保存为 server.py 并访问 localhost:5000,您应该能够看到抓取的项目。

2. Twisted-Klein + Scrapy

其他更好的方法是使用一些现有的项目,将 Twisted 与 Werkzeug 集成并显示类似于 Flask 的 API,例如扭曲克莱因。 Twisted-Klein 允许您在与 Web 服务器相同的进程中异步运行蜘蛛。更好的是它不会阻塞每个请求,并且允许您简单地从 HTTP 路由请求处理程序返回 Scrapy/Twisted deferreds。

以下代码片段将 Twisted-Klein 与 Scrapy 集成,请注意,您需要创建自己的 CrawlerRunner 基类,以便爬虫收集项目并将其返回给调用者。这个选项更高级一点,你在与Python服务器相同的进程中运行Scrapy蜘蛛,项目不存储在文件中,而是存储在内存中(因此没有像前面的示例那样的磁盘写入/读取)。最重要的是它是异步的,并且全部在一个 Twisted Reactor 中运行。

# server.py
import json

from klein import route, run
from scrapy import signals
from scrapy.crawler import CrawlerRunner

from dirbot.spiders.dmoz import DmozSpider


class MyCrawlerRunner(CrawlerRunner):
    """
    Crawler object that collects items and returns output after finishing crawl.
    """
    def crawl(self, crawler_or_spidercls, *args, **kwargs):
        # keep all items scraped
        self.items = []

        # create crawler (Same as in base CrawlerProcess)
        crawler = self.create_crawler(crawler_or_spidercls)

        # handle each item scraped
        crawler.signals.connect(self.item_scraped, signals.item_scraped)

        # create Twisted.Deferred launching crawl
        dfd = self._crawl(crawler, *args, **kwargs)

        # add callback - when crawl is done cal return_items
        dfd.addCallback(self.return_items)
        return dfd

    def item_scraped(self, item, response, spider):
        self.items.append(item)

    def return_items(self, result):
        return self.items


def return_spider_output(output):
    """
    :param output: items scraped by CrawlerRunner
    :return: json with list of items
    """
    # this just turns items into dictionaries
    # you may want to use Scrapy JSON serializer here
    return json.dumps([dict(item) for item in output])


@route("/")
def schedule(request):
    runner = MyCrawlerRunner()
    spider = DmozSpider()
    deferred = runner.crawl(spider)
    deferred.addCallback(return_spider_output)
    return deferred


run("localhost", 8080)

将上面的内容保存在文件 server.py 中,并将其放置在您的 Scrapy 项目目录中, 现在打开 localhost:8080,它将启动 dmoz Spider 并将抓取的项目作为 json 返回到浏览器。

3.ScrapyRT

当您尝试在蜘蛛前面添加 HTTP 应用程序时,会出现一些问题。例如,有时您需要处理蜘蛛日志(在某些情况下可能需要它们),您需要以某种方式处理蜘蛛异常等。有些项目允许您以更简单的方式向蜘蛛添加 HTTP API,例如ScrapyRT。这是一个向您的 Scrapy 蜘蛛添加 HTTP 服务器并为您处理所有问题的应用程序(例如处理日志记录、处理蜘蛛错误等)。

所以安装ScrapyRT后你只需要执行以下操作:

> scrapyrt 

在你的Scrapy项目目录中,它将启动HTTP服务器来监听请求。然后您访问它应该启动你的蜘蛛,为你爬行给定的网址。

免责声明:我是 ScrapyRt 的作者之一。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何整合 Flask 和 Scrapy? 的相关文章

  • DataFrame 在函数内部修改

    我面临一个我以前从未观察到的函数内数据帧修改的问题 有没有一种方法可以处理这个问题 以便初始数据帧不被修改 def test df df tt np nan return df dff pd DataFrame data 现在 当我打印时d
  • 子进程改变目录

    我想在子目录 超级目录中执行脚本 我需要首先进入该子目录 超级目录 我无法得到subprocess进入我的子目录 tducin localhost Projekty tests ve python Python 2 7 4 default
  • 如何从谷歌云存储桶读取音频文件并在datalab笔记本中使用ipd播放

    我想在数据实验室笔记本中播放我从谷歌云存储桶中读取的声音文件 这个怎么做 import numpy as np import IPython display as ipd import librosa import soundfile as
  • 如何找到列表S的所有分区为k个子集(可以为空)?

    我有一个唯一元素列表 比方说 1 2 我想将其拆分为 k 2 个子列表 现在我想要所有可能的子列表 1 2 1 2 2 1 1 2 我想分成 1 1 2 我怎样才能用 Python 3 做到这一点 更新 我的目标是获取 N 个唯一数字列表的
  • 网页抓取 - 前往第 2 页

    如何访问数据集的第二页 无论我做什么 它都只返回第 1 页 import bs4 from urllib request import urlopen as uReq from bs4 import BeautifulSoup as sou
  • 如何使用 Python 多处理避免在分叉进程中加载​​父模块

    当您创建一个Pool使用Python的进程multiprocessing 这些进程将分叉 父进程中的全局变量将显示在子进程中 如下面的问题所述 如何限制多处理进程的范围 https stackoverflow com questions 2
  • 一起使用 Flask 和 Tornado?

    我是以下的忠实粉丝Flask 部分是因为它很简单 部分是因为它有很多扩展 http flask pocoo org extensions 然而 Flask 是为了在 WSGI 环境中使用而设计的 而 WSGI 不是非阻塞的 所以 我相信 它
  • 参数验证,Python 中的最佳实践[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 让我们举一个 API 的例子 def get abs directory self path if os path isdir path ret
  • 如何在C++中列出Python模块的所有函数名称?

    我有一个 C 程序 我想导入一个 Python 模块并列出该模块中的所有函数名称 我该怎么做 我使用以下代码从模块中获取字典 PyDictObject pDict PyDictObject PyModule GetDict pModule
  • 如何强制 Y 轴仅使用整数

    我正在使用 matplotlib pyplot 模块绘制直方图 我想知道如何强制 y 轴标签仅显示整数 例如 0 1 2 3 等 而不显示小数 例如 0 0 5 1 1 5 2 等 我正在查看指导说明并怀疑答案就在附近matplotlib
  • 使用Beam IO ReadFromPubSub模块时,可以在Python中提取带有属性的消息吗?尚不清楚是否支持

    尝试将具有存储在 PubSub 中的属性的消息拉取到 Beam 管道中 我想知道是否添加了对 Python 的支持 这就是我无法阅读它们的原因 我看到它存在于Java中 pipeline options PipelineOptions pi
  • 如何向 SCons 构建添加预处理和后处理操作?

    我正在尝试在使用 SCons 构建项目时添加预处理和后处理操作 SConstruct 和 SConscript 文件位于项目的顶部 预处理动作 生成代码 通过调用不同的工具 gt 不知道在此预处理之后将生成的确切文件 可以创建用于决定生成哪
  • Spyder 如何在同一线程的后台运行 asyncio 事件循环(或者确实如此?)

    我已经研究 asyncio 模块 功能几天了 因为我想将它用于我的应用程序的 IO 绑定部分 并且我认为我现在对它的工作原理有一个合理的理解 或者在至少我认为我已经理解了以下内容 任一时刻 任一线程中只能运行一个异步事件循环 一旦一切都设置
  • 为什么 bot.get_channel() 会产生 NoneType?

    我正在制作一个 Discord 机器人来处理公告命令 当使用该命令时 我希望机器人在特定通道中发送一条消息 并向用户发送一条消息以表明该命令已发送 但是 我无法将消息发送到频道 我尝试了这段代码 import discord import
  • 如何设置 matplotlib 表中列的背景颜色

    我在一个目录中有多个 txt 文件 例如 d memdump 0 txt 1 txt 10 txt 示例文本文件如下 Applications Memory Usage kB Uptime 7857410 Realtime 7857410
  • 最小硬币找零问题——回溯

    我正在尝试用最少数量的硬币解决硬币找零问题 采用回溯法 我实际上已经完成了它 但我想添加一些选项 按其单位打印硬币数量 而不仅仅是总数 这是我下面的Python代码 def minimum coins coin list change mi
  • 获取调用者文件的绝对路径

    假设我在不同的目录中有两个文件 1 py 比如说 在C FIRST FOLDER 1 py and 2 py 比如说 在C SECOND FOLDER 2 py 文件1 py进口2 py using sys path insert 0 pa
  • 在Python中从日期时间中减去秒

    我有一个 int 变量 它实际上是秒 让我们调用这个秒数X 我需要得到当前日期和时间 以日期时间格式 减去的结果X秒 Example If X是 65 当前日期是2014 06 03 15 45 00 那么我需要得到结果2014 06 03
  • Python 枚举子集迭代

    我想迭代以下枚举的子集 class Items enum Enum item1 0 item2 1 item3 2 item4 3 item5 4 item6 5 item7 6 item8 7 说我想 for item in Items
  • 从数据集的给定日期范围中提取属于一天的数据

    我有一个数据集 日期范围为 2018 年 1 月 12 日到 8 月 3 日 其中包含一些值 维数为my df数据框是 my df shape 9752 2 每行包含半小时频率 第一行开始于2018 01 12 my df iloc 0 D

随机推荐

  • SignalR 不支持 Windows 集成身份验证

    我有一个 ASP NET MVC 4 应用程序 NET 4 5 SIignalR 可以很好地处理基于表单的身份验证 通过 IIS IIS Express 托管 一旦我将应用程序更改为 Windows 集成身份验证
  • 部署到 Elastic Beanstalk 时运行 Django 迁移

    我在 Elastic Beanstalk 上设置了 Django 应用程序 最近对数据库进行了更改 我希望现在将其应用到实时数据库 我知道我需要将其设置为容器命令 在检查数据库后我可以看到迁移已运行 但我不知道如何对迁移进行更多控制 例如
  • 如何获取当前正在显示的tableView的indexPath.row?

    我有一个包含许多值的 tableView 我想获得第一indexPath row当前正在显示的表的值 我怎样才能做到这一点 我在实现 krishnabhadra 的答案时遇到以下错误 出现错误的行是 self table scrollToR
  • urllib 下载在线目录的内容

    我正在尝试制作一个程序 该程序将打开一个目录 然后使用正则表达式来获取幻灯片的名称 然后在本地创建文件并复制其内容 当我运行它时 它似乎可以工作 但是当我实际尝试打开文件时 他们一直说版本错误 from urllib request imp
  • 将 awk 与列值条件结合使用

    我正在学习 awkAWK 编程语言我对其中一个例子有疑问 如果我想打印 3 如果 2 等于一个值 例如1 我正在使用这个运行良好的命令 awk 2 1 print 3
  • 从 angularjs 中的服务调用控制器函数

    我正在使用 socket io 在我的应用程序中启用聊天 并且我正在使用一项服务SocketService执行所有套接字操作 当消息到来时 我想从服务触发控制器的功能SocketService对 UI 进行一些更改 所以我想知道如何从服务访
  • 如何在 redux 操作(或操作中分配的其他回调)上下文中使用 jest 测试 `image.onload`

    我的问题是我正在尝试对一个函数进行单元测试 但不知道如何测试它的一部分 这是一个 React Redux 操作 执行以下操作 1 使用图像 url 检索 json 数据 2 将图像加载到 Image 实例中并将其大小分派给减速器 当使用 I
  • document.write 的替代品是什么?

    在教程中我学会了使用document write 现在我明白 许多人对此不以为然 我试过了print 但随后它实际上将其发送到打印机 那么我应该使用什么替代方案 为什么我不应该使用document write w3schools 和 MDN
  • JavaScript 中现有的 OCR 脚本 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我有一个 CMS 增强功能的想法 从图像 例如扫描文档 中提取文本信息 并且想知道是否已经有任何东西可以帮助我 基本上 我想知道是否有一个用 Jav
  • 当iframe的来源是javascript时浏览器会做什么

    当 iframe 的来源是 javascript as in 到底是怎么回事 src javascript 是什么意思告诉浏览器做什么 path src 有什么作用 谢谢 克里斯 它告诉浏览器显示执行空字符串文字的结果 因此 它只会显示一个
  • 如何在客户端检查 YouTube 上是否存在视频

    我在做验证我的Youtube网址文本字段 我需要检查一下 如果Youtubeurl不存在我应该抛出错误 我按照这个answer并创建了jsfiddle检查它 它适用于有效的 url 但不适用于无效的 url 我所看到的只是 404 错误ne
  • Objective-C 中的异步调用

    我正在尝试从网站 xml 获取数据 一切正常 但是 UIButton 一直处于按下状态 直到返回 xml 数据 因此如果互联网服务出现问题 则无法纠正 并且应用程序实际上无法使用 以下是通话内容 AppDelegate appDelegat
  • Android studio 1.5.1:找不到属性“vectorDrawables”

    我正在使用 Android Studio 1 5 1 Gradle 2 8 和我的项目最小 sdk 版本 14 目标 sdk 版本 23 所以 当我通过 Google 文档将 vectorDrawables 添加到配置时 添加了 Vecto
  • 如何在字符串集合中高效查找指定长度的相同子串?

    我有一个收藏S 通常包含 10 50 个长字符串 出于说明目的 假设每个字符串的长度范围在 1000 到 10000 个字符之间 我想找到指定长度的字符串k 通常在 5 到 20 的范围内 是每个字符串的子串S 显然 这可以使用一种简单的方
  • UIButton改变位置

    我在 IB 中设置了一个按钮 我设置了 IBOutlet 并链接到它的屏幕对象 有没有办法以编程方式更改按钮位置和 或大小 我知道您可以更改标题和某些内容 但我不知道如何更改其位置或大小 现在我想相应地改变它的位置 是否可以 如果是 请告诉
  • Javascript:找到字符串中最长的单词

    function longestWord string var str string split var longest 0 var word null for var i 0 i lt str length 1 i if longest
  • 如何从剔除绑定中获取 DOM 元素?

    我已经使用淘汰赛将 DOM 元素绑定到 viewModel 当我更改底层模型上的属性时 它会更改 DOM 一切正常 但是 有没有办法获取绑定的 DOM 元素 以便当底层模型从外部更新时我可以向其中添加一个类 我使用了自定义绑定 它使我可以访
  • 什么时候可以完全优化掉 volatile 变量?

    考虑这个代码示例 int main void volatile int a static volatile int b volatile int c c 20 static volatile int d d 30 volatile int
  • 无法在 android studio 中创建 AVD

    我是安卓新手 我刚刚安装了 Android Studio 并创建了一个默认项目 现在我正在尝试创建 AVD 但无法创建 确定按钮未启用 请帮忙 附截图 问题是你没有安装系统镜像 请检查下图 要启动 SDK 管理器 请单击 Android S
  • 如何整合 Flask 和 Scrapy?

    我正在使用 scrapy 来获取数据 我想使用 Flask Web 框架在网页中显示结果 但我不知道如何调用烧瓶应用程序中的蜘蛛 我尝试过使用CrawlerProcess呼叫我的蜘蛛 但我收到这样的错误 ValueError ValueEr