Добрый день,
Я пытаюсь очистить GitHub с помощью Scrapy. Он работает по большей части, но некоторые страницы загружают «участников» после завершения загрузки самой страницы.
Когда Scrapy встречает такую страницу, он выдает следующую ошибку:
AttributeError: 'NoneType' object has no attribute 'strip'
и отбрасывает все остальное с этого URL.
Есть ли способ сделать исключение внутри «yield», чтобы Scrapy поместил «None» в результирующий .CSV вместо того, чтобы выбросить все данные?
Вот соответствующий код:
rules = [
Rule(LinkExtractor(allow=('Repositories'), restrict_xpaths=('//a[@rel="next"]'))),
Rule(LinkExtractor(allow=('github'), restrict_xpaths=('//h3/a[@class="v-align-middle"]')), callback='parse_project'),
Rule(LinkExtractor(allow=('commits/master'), restrict_xpaths=('//*[@class="commits"]/a')), follow=True, callback='parse_commits_page'),
Rule(LinkExtractor(deny=('\+174'), restrict_xpaths=('//a[contains(text(), "Older")]')), follow=True, callback='parse_commits_page')
]
# Parse the main page of the project
def parse_project(self, response):
yield {
'author': response.xpath('//a[@rel="author"]/text()').extract(),
'name': response.xpath('//strong[@itemprop="name"]/a/text()').extract(),
'tags': [x.strip() for x in response.xpath('//a[contains(@class, "topic-tag")]/text()').extract()],
'about': response.xpath('//*[@itemprop="about"]/text()').extract_first().strip(),
'lang_name': response.xpath('//span[@class = "lang"]/text()').extract(),
'lang_perc' : response.xpath('//span[@class = "percent"]/text()').extract(),
'stars': response.xpath('//a[contains(@aria-label, "starred")]/text()').extract_first().strip(),
'forks': response.xpath('//a[contains(@aria-label, "forked")]/text()').extract_first().strip(),
'commits': response.xpath('//a[contains(., "commits")]/span/text()').extract_first().strip(),
'contributors': response.xpath('//a[contains(., "contributor")]/span/text()').extract_first().strip(),
'last_commits': None
}
В частности, 'contributors': response.xpath('//a[contains(., "contributor")]/span/text()').extract_first().strip(),
- это та часть, которая доставляет мне неприятности и где я хочу исключения.
P.S. Я также пытался заставить его ждать страницы, используя "scrapy-splash"
def pre_parse_project(self, response):
yield scrapy_splash.SplashRequest(response.url, self.parse_project,
args={
'wait': 4,
}
)
но проблема не исчезла, поэтому я хотел бы, по крайней мере, получить все данные, которые я могу, и заполнить число участников, использующих API.