#python #web-scraping #scrapy
#python #очистка веб-страниц #scrapy
Вопрос:
Мой вопрос в том, означает ли этот журнал, что веб-сайт не может быть очищен? Я изменил свой пользовательский агент, чтобы он выглядел как браузер, но это не помогло. Кроме того, я опустил «s» внутри «start_requests», но это тоже не помогло. Даже я изменил «ROBOTSTXT_OBEY = False» в seetings.py но это не помогло.
Вот журнал, который я получил:
2020-11-17 18:06:41 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2020-11-17 18:06:41 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2020-11-17 18:06:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/robots.txt> (referer: None)
2020-11-17 18:06:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: None)
2020-11-17 18:06:43 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: https://podcasts.apple.com/us/genre/podcasts-arts/id1301)
2020-11-17 18:06:43 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts-books/id1482> (referer: https://podcasts.apple.com/us/genre/podcasts-arts/id1301)
2020-11-18 17:29:49 [scrapy.core.engine] INFO: Closing spider (finished)
2020-11-18 17:29:49 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 1342,
'downloader/request_count': 4,
'downloader/request_method_count/GET': 4,
'downloader/response_bytes': 67297,
'downloader/response_count': 4,
'downloader/response_status_count/200': 4,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2020, 11, 18, 13, 59, 49, 133234),
'httpcache/hit': 4,
'log_count/DEBUG': 5,
'log_count/INFO': 9,
'request_depth_max': 2,
'response_received_count': 4,
'robotstxt/request_count': 1,
'robotstxt/response_count': 1,
'robotstxt/response_status_count/200': 1,
'scheduler/dequeued': 3,
'scheduler/dequeued/memory': 3,
'scheduler/enqueued': 3,
'scheduler/enqueued/memory': 3,
'start_time': datetime.datetime(2020, 11, 18, 13, 59, 48, 758371)}
2020-11-18 17:29:49 [scrapy.core.engine] INFO: Spider closed (finished)
Вот часть моего паука:
import scrapy
class ApplePodcastSpider(scrapy.Spider):
name = 'apple_podcast'
allowed_domains = ['podcasts.apple.com']
def start_requests(self):
yield scrapy.Request(url='https://podcasts.apple.com/us/genre/podcasts-arts/id1301',
callback= self.parse_categories, dont_filter=True)
def parse_categories(self, response):
categories=response.xpath("//ul[@class='list column first']")
for category in categories:
category_name=category.xpath(".//li/a/text()").get()
category_link=category.xpath(".//li/a/@href").get()
yield response.follow(url=category_link, callback=self.parse_sub_categories, meta={'category_name': category_name}, dont_filter=True)
def parse_sub_categories(self, response):
category_name=response.request.meta['category_name']
sub_categories=response.xpath("//ul[@class='list column first']/li")
for sub_category in sub_categories:
sub_category_name=sub_category.xpath(".//ul[@class='list top-level-subgenres']/li/a/text()").get()
sub_category_link=sub_category.xpath(".//ul[@class='list top-level-subgenres']/li/a/@href").get()
if sub_category_link is None:
pass
else:
yield response.follow(url=sub_category_link, callback=self.parse_alphabet, meta={'category_name': category_name,'sub_category_name': sub_category_name}, dont_filter=True)
def parse_alphabet(self,response):
category_name=response.request.meta['category_name']
sub_category_name=response.request.meta['sub_category_name']
alphabets=response.xpath("//div[@class='content']/div[@class='padder']/div[@class='selectedgenre']")
for alphabet in alphabets:
alphabet_link=alphabet.xpath(".//ul[@class='list alpha']/li/a[@class='selected']/@href").get()
yield response.follow(url=alphabet_link, callback=self.parse_podcasts_link, meta={'category_name': category_name, 'sub_category_name': sub_category_name}, dont_filter=True)
def parse_podcasts_link(self, response):
category_name=response.request.meta['category_name']
sub_category_name=response.request.meta['sub_category_name']
podcasts=response.xpath("//div[@class='grid3-column']")
for podcast in podcasts:
podcast_name=podcast.xpath(".//div[@class='column first']/ul/li/a/text()").get()
podcast_link=podcast.xpath(".//div[@class='column first']/ul/li/a/@href").get()
for podcast in podcasts:
podcast_name=podcast.xpath(".//div[@class='column']/ul/li/a/text()").get()
podcast_link=podcast.xpath(".//div[@class='column']/ul/li/a/@href").get()
for podcast in podcasts:
podcast_name=podcast.xpath(".//div[@class='column last']/ul/li/a/text()").get()
podcast_link=podcast.xpath(".//div[@class='column last']/ul/li/a/@href").get()
yield response.follow(url=podcast_link, callback=self.parse_podcasts, meta={'category_name':category_name,'sub_category_name':sub_category_name,'podcast_name':podcast_name}, dont_filter=True)
def parse_podcasts(self, response):
category_name = response.request.meta['category_name']
sub_category_name = response.request.meta['sub_category_name']
podcast_name = response.request.meta['podcast_name']
podcasts = response.xpath("//div[@class='ember-view l-content-width section section--hero product-hero']/section[@class='ember-view']/div[@class='l-row']")
for podcast in podcasts:
rate = podcast.xpath(".//div[@class='l-column small-12 medium-7 large-8 small-valign-top']/div[@class='l-row']/div[@class='l-column small-7 medium-12 small-valign-top']/header[@class='product-header product-header--padded-start podcast-header']/ul[@class='product-header__list podcast-header__list']/li[2]//ul[@class='inline-list inline-list--mobile-compact']/li[@class='inline-list__item']/figure/figcaption/text()[1]").get()
rating_number = podcast.xpath(".//div[@class='l-column small-12 medium-7 large-8 small-valign-top']/div[@class='l-row']/div[@class='l-column small-7 medium-12 small-valign-top']/header[@class='product-header product-header--padded-start podcast-header']/ul[@class='product-header__list podcast-header__list']/li[2]//ul[@class='inline-list inline-list--mobile-compact']/li[@class='inline-list__item']/figure/figcaption/text()[3]").get()
yield{
'category_name':category_name,
'sub_category_name':sub_category_name,
'podcast_name':podcast_name,
'rate':rate,
'rating_number':rating_number
}
next_page=response.xpath("//div[@class='content']/div[@class='padder']/div[@class='selectedgenre']/ul[@class='list paginate']/li/a[@class='selected']/@href").get()
if next_page:
yield scrapy.Request(url=next_page, callback=self.parse_podcasts, dont_filter=True)
Кто-нибудь может помочь мне понять, в чем проблема и как я могу ее решить?
Спасибо!!!
—ПРАВКА1—
Журнал, который я получил после изменения части «allowed_domains»:
2020-11-18 13:49:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2020-11-18 13:49:18 [scrapy.extensions.httpcache] DEBUG: Using filesystem cache storage in C:Usersshimaprojectsapple_podcasts.scrapyhttpcache
2020-11-18 13:49:18 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2020-11-18 13:49:18 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/robots.txt> (referer: None) ['cached']
2020-11-18 13:49:18 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: None) ['cached']
2020-11-18 13:49:18 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: https://podcasts.apple.com/us/genre/podcasts-arts/id1301) ['cached']
2020-11-18 13:49:18 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts-books/id1482> (referer: https://podcasts.apple.com/us/genre/podcasts-arts/id1301) ['cached']
—EDIT2—
Журнал, который я получил после удаления инструкции «try and except»:
2020-11-18 13:53:07 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2020-11-18 13:53:07 [scrapy.extensions.httpcache] DEBUG: Using filesystem cache storage in C:Usersshimaprojectsapple_podcasts.scrapyhttpcache
2020-11-18 13:53:07 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2020-11-18 13:53:07 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/robots.txt> (referer: None) ['cached']
2020-11-18 13:53:07 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: None) ['cached']
2020-11-18 13:53:07 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: https://podcasts.apple.com/us/genre/podcasts-arts/id1301) ['cached']
2020-11-18 13:53:07 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts-books/id1482> (referer: https://podcasts.apple.com/us/genre/podcasts-arts/id1301) ['cached']
Комментарии:
1. Вам не нужно добавлять
www
allowed_domains
значение. Попробуйте заменитьwww.podcasts.apple.com
podcasts.apple.com
наallowed_domains
переменную in . см.: docs.scrapy.org/en/latest/topics /…2. Я бы предположил, что проблема в том, что вы обернули все свои методы класса в try, кроме блоков, которые будут препятствовать правильному выполнению spider. Вы должны удалить это и исправить отступ.
3. Спасибо, @ShubhamKadam. Я сделал то, что вы сказали, и отредактировал сообщение, чтобы увидеть полученный мной журнал (EDIT1).
4. Спасибо, @Patrick Klein, я удалил «попробуйте и исключите» и отредактировал сообщение в EDIT2, чтобы увидеть журнал, который я получил
5. Означает ли это, что я забанен или что-то в этом роде?
Ответ №1:
В вашем журнале выполнения нет ничего неправильного.
2020-11-17 18:06:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://podcasts.apple.com/us/genre/podcasts-arts/id1301> (referer: None)
Это отладочные сообщения, они сообщают вам, что ваш spider просканировал указанный URL-адрес. Если вы не хотите его видеть, вы можете LOG_LEVEL='INFO'
использовать свой settings.py
.
Кроме того, вы не определили какие-либо элементы для очистки, просто определили страницы для обхода, поэтому паук будет просматривать страницы и в конечном итоге закрываться.
Редактировать:
Я не проверял весь ваш код, но я выполнил один раз и заметил несколько проблем.
Этот селектор вернет пустой:
alphabets=response.xpath("//div[@class='content']/div[@class='padder']/div[@class='selectedgenre']")
Вы использовали @class
вместо @id
для обоих 'content'
и 'selectedgenre'
. XPath должен быть:
//div[@id='content']/div[@class='padder']/div[@id='selectedgenre']
Обратите внимание, что это вернет только ОДИН селектор, поэтому вам не следует перебирать его. Вероятно, вы хотите выполнить итерацию по ссылкам.
Это также вернет пустой:
alphabet_link=alphabet.xpath(".//ul[@class='list alpha']/li/a[@class='selected']/@href").get()
Поскольку a
в используемом вами XPath нет элемента с классом 'selected'
(по умолчанию).
Я полагаю, что будет больше неработающих XPaths, поэтому вам следует просмотреть селекторы, чтобы убедиться, что ваши XPaths верны и что они возвращают то, что вы ожидаете. Никаких проблем, связанных с robots.txt
btw.
Комментарии:
1. Спасибо, @renatodvc. Я отредактировал сообщение и поместил туда весь код паука. Я предположил, что это может быть необязательно, поэтому я просто вставил часть кода моего паука. На самом деле, я попросил его очистить так много элементов. и теперь вы можете увидеть все это выше.
2. Проблема в том, что создается выходной XML-файл. Но когда я пытаюсь его открыть, я получаю «ошибка синтаксического анализа XML». И на основе журнала ни один элемент не очищается.