使用Scrapy将多个页面的结果抓取到一个项目中

ztigrdn8  于 2022-11-09  发布在  其他
关注(0)|答案(1)|浏览(182)

如何使用Scrapy将多个页面的结果刮到一个项目中?
应考虑的页面:

  • 原始页面o(例如,由start_requests()给出)
  • urls中的所有页url,其中urls是通过根据parse()擦除o而创建的字段。

请注意,不同ourls可能不会不相交。

具体示例

我有一个spider,它可以为条目'i'(即一个scrubed页面)生成以下字段:

  • id
  • prio
  • urls

urls是一个url列表,对于每个url(不是死的),我想从url中提取一些信息来扩展i的字段

  • image_list
  • head_list

最后,我希望对结果项进行筛选,以便对于每个id,只保留具有最高prio的项。

我所尝试的

因为我已经读到所有的抓取都应该在spider中完成(而不是在items pipeline组件中),所以我认为最好的方法是通过以下方式将抓取与后处理分离:
1.使用一个蜘蛛,它从起始页面收集所有数据,通过parse将数据解析成i,然后为iurls中的每个URL调用response.follow(url, callback=self.parse_given_url, meta={'item':i})

  1. parse_given_url会将元数据提取到i中,解析给定的url,并将image_listhead_list添加到i
    1.通过项目流水线组件对所有的抓取数据进行所有的后处理(合并和过滤),以获得所有的最终项目。
    我的方法的一个最小的可重复的例子:
import scrapy

class Minimal(scrapy.Spider):
    name = "minimal"

    def start_requests(self):
        url = 'https://www.arztsuche-bw.de/index.php?suchen=1&id_fachgruppe=441&arztgruppe=facharzt&plz=761&direction=ASC'
        yield scrapy.Request(url=url, method="POST", callback=self.parse)

    def parse(self, response):
        for office in response.css('li.row.resultrow.even') + response.css('li.row.resultrow.odd'):
            full_name = office.css('dd.name dl').xpath('string(.//dt[1])').get()
            contact_selectors = office.css('dd.adresse dl dd')
            urls = contact_selectors.xpath('.//a[@title="Homepage aufrufen"]/@href').getall()
            office_data = {
                'name': full_name,
                'url': urls,
            }
            if urls:
                for url in urls:
                    yield response.follow(url, callback=self.parse_hp, meta={'item':office_data})
            else:
                yield office_data

    def parse_hp(self, response):
        office_data = response.meta['item']

        return {
          **office_data,
            'hp_head': response.xpath('//h1/text()').get(),
            'hp_logo_image': response.xpath('//img/@src').get(),
        }

然而,由于来自不同项的urls字段不是不相交的,所以来自response.follow_all()调用的一些请求被丢弃,因此结果项丢失。我可以将参数dont_filter=True添加到response.follow_all()调用中,但是这样一个url可能会被多次抓取,这是我希望避免的。因此,我感觉我的方法不正确。

oymdgrw7

oymdgrw71#

要将来自主网站的信息与从各个诊所网站上挑选的信息结合起来,您可以执行以下操作(编辑:包括custom_settings,以及没有网站的重定向到“google.com”,现在它将产生63个结果中的56个-需要进一步调试):

import scrapy
from german_medical.items import GermanMedicalItem

class DoctorsSpider(scrapy.Spider):
    name = 'doctors'
    custom_settings = {
        'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter',
    }
    allowed_domains = []
    start_urls = ['https://www.arztsuche-bw.de/index.php?suchen=1&offset=0&id_z_arzt_praxis=0&id_fachgruppe=441&id_zusatzbezeichnung=0&id_genehmigung=0&id_dmp=0&id_zusatzvertraege=0&id_sprache=0&vorname=&nachname=ohne+Titel+%28Dr.%29&arztgruppe=facharzt&geschlecht=alle&wochentag=alle&zeiten=alle&fa_name=&plz=761&ort=&strasse=&schluesselnr=&schluesseltyp=lanr7&landkreis=&id_leistungsort_art=0&id_praxis_zusatz=0&sorting=name&direction=ASC&checkbox_content=&name_schnellsuche=&fachgebiet_schnellsuche=']
    offset = 20
    def parse(self, response):
        doctor_cards = response.xpath('//ul[contains(@class, "resultlist")]/li[contains(@class, "resultrow")]')
        for d in doctor_cards:
            full_name = ' '.join(d.xpath('.//dd[@class="name"]/dl/dt/text()').extract())
            address = ', '.join(d.xpath('.//dd[@class="adresse"]/p[@class="anschrift-arzt"]/text()').extract()[1:])
            urls = [x for x in d.xpath('.//dd[@class="adresse"]/p[@class="anschrift-arzt"]/following-sibling::dl//a/@href').extract() if 'mailto:' not in x ]
            resp_meta = {
                'full_name': full_name,
                'address': address,
                'urls': urls 
            }
            if not urls:
                urls = ['https://google.com']
            for url in urls:
                print(url)    
                yield response.follow(url=url, callback = self.parse_doctor_clinik, meta = resp_meta)

        next_page = 'https://www.arztsuche-bw.de/index.php?suchen=1&offset=' + str(self.offset) + '&id_z_arzt_praxis=0&id_fachgruppe=441&id_zusatzbezeichnung=0&id_genehmigung=0&id_dmp=0&id_zusatzvertraege=0&id_sprache=0&vorname=&nachname=ohne+Titel+%28Dr.%29&arztgruppe=facharzt&geschlecht=alle&wochentag=alle&zeiten=alle&fa_name=&plz=761&ort=&strasse=&schluesselnr=&schluesseltyp=lanr7&landkreis=&id_leistungsort_art=0&id_praxis_zusatz=0&sorting=name&direction=ASC&checkbox_content=&name_schnellsuche=&fachgebiet_schnellsuche='
        print(next_page)
        if self.offset < 80:
            self.offset += 20
            yield response.follow(next_page, callback = self.parse)

    def parse_doctor_clinik(self, response):
        items  = GermanMedicalItem()
        try:
            website_header = response.xpath('//h1/text()').get() if response.xpath('//h1/text()') else None
            logo_url = response.xpath('//img/@src').get() if response.xpath('//img/@src') else None
        except Exception as e:
            website_header = 'Not specified'
            logo_url = 'Not specified'
        items['full_name'] = response.request.meta['full_name']
        items['address'] = response.request.meta['address']
        items['office_urls'] = response.request.meta['urls']
        items['website_header'] = website_header
        items['logo_url'] = logo_url

        yield items

您的items.py文件应如下所示:


# Define here the models for your scraped items

# 

# See documentation in:

# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy

class GermanMedicalItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    full_name = scrapy.Field()
    office_urls = scrapy.Field()
    address = scrapy.Field()
    website_header = scrapy.Field()
    logo_url = scrapy.Field()

使用scrapy crawl doctors -o doctors_germ.json运行,您会得到一个json文件,如下所示:

[
{"full_name": "Dr. med. Jan Gestrich Sprechstundenzeiten ", "address": "Zeppelinstr. 2, 76185 Karlsruhe, Ortsteil: Gr\u00fcnwinkel, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.ka-nephrologie.de"], "website_header": "Diagnostik und Therapie in unserer Nephrologischen Praxis", "logo_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII="},
{"full_name": "Dr. med. Martin Andre Sprechstundenzeiten ", "address": "S\u00fcdendstr. 47-49, 76137 Karlsruhe, Ortsteil: S\u00fcdweststadt, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.nephrologie-karlsruhe.de"], "website_header": null, "logo_url": "https://static.wixstatic.com/media/689a07_b6517c8c92574851a08a4b37c9a23142~mv2.jpg/v1/fill/w_101,h_72,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/Logo_Nephro_neu.jpg"},
{"full_name": "Dr. med. Kathrin Drognitz Sprechstundenzeiten ", "address": "Moltkestr. 90, 76133 Karlsruhe, Ortsteil: Nordstadt, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.klinikum-karlsruhe.de/einrichtungen/spezielle-medizinische-einrichtungen/"], "website_header": "Spezielle medizinische Einrichtungen", "logo_url": "data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%20100%20100'%2F%3E"},
{"full_name": "Dr. med. Thorsten Dorn Sprechstundenzeiten ", "address": "Kriegsstr. 140, 76133 Karlsruhe, Ortsteil: Innenstadt-West, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.hormone-karlsruhe.de"], "website_header": null, "logo_url": "/templates/web_joomla_neu/images/spacer.gif"},
{"full_name": "Dr. med. Wilhelm Hausch Sprechstundenzeiten ", "address": "Lammstr. 21, 76133 Karlsruhe, Ortsteil: Innenstadt-West, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.gastroenterologie-karlsruhe.de"], "website_header": "Herzlich Willkommen in der Praxis f\u00fcr Gastroenterologie am Ettlinger Tor.", "logo_url": "/assets/asset.babb34fd.png"},
{"full_name": "Dr. med. Norbert Bruhn Sprechstundenzeiten ", "address": "Gartenstr. 71, 76135 Karlsruhe, Ortsteil: S\u00fcdweststadt, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.praxis-bruhn.com"], "website_header": null, "logo_url": "https://www.praxis-bruhn.com/s/img/emotionheader7307447.jpg?1472391703.667px.483px"},
{"full_name": "Dr. med. Kurt Beier Sprechstundenzeiten ", "address": "Ludwig-Erhard-Allee 24, 76131 Karlsruhe, Ortsteil: Innenstadt-Ost, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.deRossi.de", "https://www.medGAIN.de"], "website_header": "\r\n\t\t\t\t\r\n\t\t\t\t\tmedGAIN | Praxis Dr. med. Thomas de Rossi und Kollegen\r\n\t\t\t\t\r\n\t\t\t\t", "logo_url": "img/med_gain_logo.svg"},
{"full_name": "Dr. med. Kai Haberl Sprechstundenzeiten ", "address": "Waldstra\u00dfe 41-43, 76133 Karlsruhe, Ortsteil: Innenstadt-West, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.kardiologie-waldstrasse.de"], "website_header": " Unser Team hei\u00dft Sie herzlich willkommen! ", "logo_url": "images/logo_kardiologie_karlsruhe.svg"},
{"full_name": "Dr. med. Lutz Krieglstein Sprechstundenzeiten ", "address": "Hans-Sachs-Str. 1, 76133 Karlsruhe, Ortsteil: Weststadt, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.praxis-muehlburger-tor.de"], "website_header": "Gastroenterologische Gemeinschaftspraxis in Karlsruhe", "logo_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAC0lEQVQYV2NgAAIAAAUAAarVyFEAAAAASUVORK5CYII="},
{"full_name": "Dr. med. Mirko Krivokuca Sprechstundenzeiten ", "address": "Kaiserallee 30, 76185 Karlsruhe, Ortsteil: Weststadt, Landkreis: Karlsruhe - Stadt", "office_urls": ["https://www.kardiologie-musikerviertel.de"], "website_header": "Fieber\n?\u00a0\u00a0\u00a0 Husten?\u00a0\u00a0\u00a0 Atemwegsinfekt?", "logo_url": "https://image.jimcdn.com/app/cms/image/transf/none/path/sb3d393a4e68b5222/image/i855f937e8779839c/version/1608138272/image.jpg"},
....
    ]

相关问题