Веб-сканирование и извлечение данных с помощью scrapy

Я новичок в python, а также в scrapy. Я пытаюсь просканировать исходный URL https://www.health.com/patients/status/.This исходный URL-адрес содержит много URL-адресов. Но я хочу получить только URL-адреса, которые содержат Faci / Details / # somenumber из исходного URL-адреса. URL-адрес будет таким, как показано ниже:

https://www.health.com/patients/status/ ->https://www.health.com/Faci/Details/2                                                                                                        
                                   -> https://www.health.com/Faci/Details/3
                                   -> https://www.health.com/Faci/Details/4



https://www.health.com/Faci/Details/2 -> https://www.health.com/provi/details/64
                                 -> https://www.health.com/provi/details/65


https://www.health.com/Faci/Details/3 -> https://www.health.com/provi/details/70
                                 -> https://www.health.com/provi/details/71

На каждой странице https://www.health.com/Faci/Details/2 есть https://www.health.com/provi/details/64 https://www.health.com/provi/details/65 .... Наконец, я хочу получить некоторые данные из https://www.health.com/provi/details/#somenumber url. Как добиться того же?

На данный момент я пробовал приведенный ниже код из учебника scrapy и могу сканировать только URL-адрес, который содержит https://www.health.com/Faci/Details/#somenumber. Он не собирается https://www.health.com/provi/details/#somenumber. Я пытался установить ограничение глубины в файле settings.py, но это не сработало.

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from news.items import NewsItem


class MySpider(CrawlSpider):
name = 'provdetails.com'
allowed_domains = ['health.com']
start_urls = ['https://www.health.com/patients/status/']

rules = (

  Rule(LinkExtractor(allow=('/Faci/Details/\d+', )),  follow=True),

  Rule(LinkExtractor(allow=('/provi/details/\d+', )),callback='parse_item'),                  
)

def parse_item(self, response):
    self.logger.info('Hi, this is an item page! %s', response.url)
    item = NewsItem()
    item['id'] = response.xpath("//title/text()").extract()
    item['name'] = response.xpath("//title/text()").extract()
    item['description'] = response.css('p.introduction::text').extract()
    filename='details.txt'
    with open(filename, 'wb') as f:
        f.write(item)
    self.log('Saved file %s' % filename)
    return item

Пожалуйста, помогите мне продолжить?


person Anonymous    schedule 14.03.2017    source источник


Ответы (1)


Честно говоря, мощный Rule/LinkExtractor, основанный на регулярных выражениях, часто доставлял мне трудности. Для простого проекта это может быть подход к извлечению всех ссылок на странице и последующему просмотру атрибута href. Если href соответствует вашим потребностям, yield новый объект Response с этим. Например:

 from scrapy.http import Request
 from scrapy.selector import Selector
...
    # follow links
    for href in sel.xpath('//div[@class="contentLeft"]//div[@class="pageNavigation nobr"]//a').extract():
            linktext = Selector(text=href).xpath('//a/text()').extract_first()
            if linktext and linktext[0] == "Weiter":
                    link = Selector(text=href).xpath('//a/@href').extract()[0]
                    url = response.urljoin(link)
                    print url
                    yield Request(url, callback=self.parse)

Некоторые замечания к вашему коду:

    response.xpath(...).extract() 

Это вернет список, возможно, вы хотите взглянуть на _7 _ которые предоставляют первый элемент (или None).

    with open(filename, 'wb') as f:

Это приведет к перезаписи файла несколько раз. Вы получите только последний сохраненный предмет. Также вы открываете файл в двоичном режиме ('b'). Судя по имени файла, вы хотите прочитать его как текст? Использовать 'a' для добавления? См. документацию open (). Альтернативой является использование _ 12_ флаг, чтобы использовать средства scrapys для хранения элементов в JSON или CSV.

    return item

Это хороший стиль - yield предметов вместо того, чтобы возвращать их. По крайней мере, если вам нужно создать несколько элементов с одной страницы, вам нужно yield их.

Еще один хороший подход: Используйте одну функцию parse () для одного типа / типа страницы.

Например, каждая страница в start_urls заполнит в конце parse(). Из этого вы можете извлечь ссылки и yield Request для каждой /Faci/Details/N страницы с помощью обратного вызова parse_faci_details(). В parse_faci_details() вы снова извлекаете интересующие ссылки, создаете Request и передаете их через callback=, например, parse_provi_details(). В этой функции вы создаете нужные вам предметы.

person rfelten    schedule 14.03.2017