需要将Scrapy回调方法数据返回给调用函数

时间:2019-06-23 00:10:05

标签: scrapy

在下面的代码中,我试图从网站收集电子邮件ID。它可以在联系方式或关于我们的页面上。 从解析方法中,我对所有这些页面都遵循extemail方法。 我从每个页面收集了一些电子邮件ID。 现在,我需要使用发送到 init 方法的原始记录来打印它们。

例如: 记录=“ https://www.wockenfusscandies.com/

我想将输出打印为 https://www.wockenfusscandies.com/|abc@gamil.com|def@outlook.com

我无法将它们存储在self.email中,并传递回 init 方法。

请帮助。

import scrapy
from scrapy.crawler import CrawlerProcess


class EmailSpider(scrapy.Spider):

    def __init__(self, record):
        self.record = record
        self.emails = []

        url = record.split("|")[4]

        if not url.startswith("http"):
            url = "http://{}".format(url)

        if url:
            self.start_urls = ["https://www.wockenfusscandies.com/"]
        else:
            self.start_urls = []

    def parse(self, response):
        contact_list = [a.attrib['href'] for a in response.css('a') if 'contact' in a.attrib['href'] or 'about' in a.attrib['href']]
        contact_list.append(response.request.url)

        for fllink in contact_list:
            yield response.follow(fllink, self.extemail)

    def extemail(self, response):
        emails = response.css('body').re('[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+')
        yield {
            'emails': emails
        }

process = CrawlerProcess({
    'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
})
f = open("/Users/kalpesh/work/data/test.csv")
for rec in f:
    process.crawl(EmailSpider, record=rec)
f.close()
process.start()

2 个答案:

答案 0 :(得分:0)

如果我正确理解了您的意图,则可以尝试以下操作:

a)收集self.mail中的邮件ID,例如

def extemail(self, response):
    emails = response.css('body').re('[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+')
    self.emails = emails.copy()
    yield {
        'emails': emails
    }

(或通过其他方式从emails获取电子邮件ID)

b)添加GitHub-Example中的close(self,reason)方法,蜘蛛完成后会调用该方法

def close(self, reason):
    mails_for_record = ""

    for mail in self.emails:
        mails_for_record += mail + "|"

    print(self.record + mails_for_record)

还请注意,我在某处读到,对于某些版本的Scrapy,它是def close(self, reason),对于其他版本,它是def closed(self, reason)

希望,此过程对您有帮助。

答案 1 :(得分:0)

在产生该站点的结果之前,您应该访问所有站点页面。 这意味着您应该具有要访问的页面队列和结果存储。 可以使用meta完成。

一些伪代码:

def parse(self, response):
    meta = response.meta
    if not meta.get('seen'):
    # -- finding urls of contact and about us pages --
    # -- putting it to meta['queue'] --
    # -- setting meta['seen'] = True

    page_emails_found = ...getting emails here...
    # --- extending already discovered emails 
    # --- from other pages/initial empty list with new ones
    meta['emails'].extend(page_emails_found)

    # if queue isn't empty - yielding new request
    if meta['queue']:
       next_url = meta['queue'].pop()
       yield Request(next_url, callback=self.parse, meta=copy(meta))
    # if queue is empty - yielding result from meta
    else:
       yield {'url': current_domain, 'emails': meta['emails']}


这样的事情。