如何使用 flask 和Scrapy在Google功能上进行Scrapy工作

kr98yfug  于 2023-02-16  发布在  Go
关注(0)|答案(1)|浏览(201)

你好,我一直在遵循这个教程:https://weautomate.org/articles/running-scrapy-spider-cloud-function/
我试图让这个网络刮刀运行在云中,并能够接收邮政请求与邮政编码,这将导致搜索的邮政编码,并返回一个地址列表的响应。
目前,我只有这个www.example.com文件和requirements.txt文件,其中有剪贴板和 flask 。main.py file and requirements.txt file with scrapy and flask in it.

from multiprocessing import Process, Queue
from flask import Flask, jsonify, request
import scrapy
from scrapy.crawler import CrawlerProcess

app = Flask(__name__)

@app.route('/start_scrape', methods=['POST'])
def start_scrape(request):
    postcode = request.get_json()['postcode']
    start_urls = [f'https://find-energy-certificate.service.gov.uk/find-a-certificate/search-by-postcode?postcode={postcode}']
    addresses = []

    class AddressesSpider(scrapy.Spider):
        name = 'Addresses'
        allowed_domains = ['find-energy-certificate.service.gov.uk']
        start_urls = start_urls

        def parse(self, response):
            for row in response.xpath('//table[@class="govuk-table"]//tr'):
                address = row.xpath("normalize-space(.//a[@class='govuk-link']/text())").extract()[0].lower()
                address = address.rsplit(',', 2)[0]
                link = row.xpath('.//a[@class="govuk-link"]/@href').extract()
                details = row.xpath("normalize-space(.//td/following-sibling::td)").extract()

                item = {
                    'link': link,
                    'details': details,
                    'address': address
                }
                addresses.append(item)

    process = scrapy.crawler.CrawlerProcess(settings={
        'ROBOTSTXT_OBEY': False
    })
    process.crawl(AddressesSpider)
    process.start()

    return jsonify(addresses)

def my_cloud_function(event, context):
    def script(queue):
        try:
            settings = scrapy.settings.Settings()
            settings.setdict({
                'ROBOTSTXT_OBEY': False
            })

            process = CrawlerProcess(settings)
            process.crawl(AddressesSpider)
            process.start()
            queue.put(None)
        except Exception as e:
            queue.put(e)

    queue = Queue()

    main_process = Process(target=script, args=(queue,))
    main_process.start()
    main_process.join()

    result = queue.get()
    if result is not None:
        raise result 

    return 'ok'

当这个脚本第一次启动时,我收到了一些错误,但它确实成功编译:
类型错误:start_scrap()接受0个位置参数,但给出了1个。view_func(/layers/google. python. pip/pip/lib/python3.10/站点包/函数框架/init. py:99)2
缺少目标异常:文件/workspace/www.example.com应该包含一个名为/start_scrape. get_user_function的函数(/layers/google. python. pip/pip/lib/python3.10/站点包/函数框架/函数注册表. py:41)1main.py is expected to contain a function named /start_scrape .get_user_function ( /layers/google.python.pip/pip/lib/python3.10/site-packages/functions_framework/_function_registry.py:41 ) 1
名称错误:未定义名称"start_urls"。地址Spider(/workspace/main.py:16)1
模块未找到错误:没有名为"scrappy"的模块。(/workspace/main.py:3)
使用-H "授权"发送 curl 帖子时:承载方$(gcloud身份验证打印标识令牌)"

  • H "内容类型:应用程序/json "
  • d '{"邮政编码":"氧合器4 + 1EU "}'
    我得到一个500错误。任何帮助来解决这个问题将是伟大的
    我一直在尝试运行这个scrapy,我希望它在发送一个邮政编码时返回一个json格式的地址列表。目前它似乎什么也没做。
tyg4sfes

tyg4sfes1#

在您的代码中,创建scrapy进程,执行启动,然后返回jsonify HTTP响应。
因此,scrappy过程在后台运行-〉这是你的问题。
事实上,使用云功能(云运行和AppEngine标准),只有在处理HTTP请求时才收费。在请求处理之外,因为不收费,所以CPU会被节流。15分钟后(使用云运行,我认为使用第一代云功能是30分钟)没有任何请求处理,示例会被卸载
因此,你不能在后台运行任何东西(或者非常慢)。如果太慢,示例会在scrap结束前被删除。
要解决这个问题,您可以使用带有最小示例选项的Cloud Run(或Cloud Functions 2nd generation,这是相同的),或者如果处理时间少于15分钟,则不使用CPU节流选项。
当然,更多的CPU使用会产生额外的费用!

相关问题