Получил ошибку выше. Пробежался по SO и только об 403 или 404 ошибках заговорил.
Вот некоторые вещи, которые я пытался заставить это работать.
И поля ошибок
2019-04-07 17:34:00 [scrapy.middleware] INFO: Enabled item pipelines:
[]
2019-04-07 17:34:00 [scrapy.core.engine] INFO: Spider opened
2019-04-07 17:34:00 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2019-04-07 17:34:00 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2019-04-07 17:34:00 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://www.reddit.com/robots.txt> from <GET http://www.reddit.com/robots.txt>
2019-04-07 17:34:00 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.reddit.com/robots.txt> (referer: None)
2019-04-07 17:34:00 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://www.reddit.com/r/gameofthrones//> from <GET http://www.reddit.com/r/gameofthrones//>
2019-04-07 17:34:01 [scrapy.core.engine] DEBUG: Crawled (501) <GET https://www.reddit.com/r/gameofthrones//> (referer: None)
2019-04-07 17:34:01 [scrapy.spidermiddlewares.httperror] INFO: Ignoring response **<501 https://www.reddit.com/r/gameofthrones//>: HTTP status code is not handled or not allowed**
2019-04-07 17:34:01 [scrapy.core.engine] INFO: Closing spider (finished)
Коды
class RedditbotSpider(scrapy.Spider):
name = "redditgetter"
allowed_domains = ['reddit.com']
start_urls = ['http://www.reddit.com/r/gameofthrones/']
custom_settings = {
'FEED_URI' : 'tmp/redditdata.csv'
}
def parse(self, response):
titles = response.css('.title.may-blank::text').extract()
votes = response.css('.score.unvoted::text').extract()
times = response.css('time::attr(title)').extract()
for item in zip(titles,votes,times):
scraped_info = {
'title' : item[0],
'vote' : item[1],
'created_at' : item[2],
}
yield scraped_info
ОБНОВЛЕНИЕ: исправлена новая ошибка после отступа и "//".
2019-04-07 23:00:44 [scrapy.core.engine] INFO: Spider opened
2019-04-07 23:00:44 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2019-04-07 23:00:44 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2019-04-07 23:00:44 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://www.reddit.com/robots.txt> from <GET http://www.reddit.com/robots.txt>
2019-04-07 23:00:45 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.reddit.com/robots.txt> (referer: None)
2019-04-07 23:00:45 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (301) to <GET https://www.reddit.com/r/gameofthrones/> from <GET http://www.reddit.com/r/gameofthrones/>
2019-04-07 23:00:47 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.reddit.com/r/gameofthrones/> (referer: None)
2019-04-07 23:00:47 [scrapy.core.engine] INFO: Closing spider (finished)
2019-04-07 23:00:47 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 1287,
'downloader/request_count': 4,
'downloader/request_method_count/GET': 4,
'downloader/response_bytes': 101351,
'downloader/response_count': 4,
'downloader/response_status_count/200': 2,
'downloader/response_status_count/301': 2,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2019, 4, 7, 15, 0, 47, 452284),
'log_count/DEBUG': 4,
'log_count/INFO': 9,
'memusage/max': 50294784,
'memusage/startup': 50290688,
'response_received_count': 2,
'robotstxt/request_count': 1,
'robotstxt/response_count': 1,
'robotstxt/response_status_count/200': 1,
'scheduler/dequeued': 2,
'scheduler/dequeued/memory': 2,
'scheduler/enqueued': 2,
'scheduler/enqueued/memory': 2,
'start_time': datetime.datetime(2019, 4, 7, 15, 0, 44, 502445)}
2019-04-07 23:00:47 [scrapy.core.engine] INFO: Spider closed (finished)
Эта проблема не имеет ничего общего с реализацией вашего кода, это просто опечатка в URL-адресе. Мне удалось воспроизвести проблему (код состояния 501
), отправив запрос GET на https://www.reddit.com/r/gameofthrones//
через https://reqbin.com/u4xxuehu.
Вам просто нужно удалить лишнюю косую черту в конце URL-адреса, чтобы получить статус 200 (OK)
: https://reqbin.com/43le52w4
Изменить, касающееся очистки Reddit: в вашем коде нет ошибки, он успешно получает ответ размером 101351 байт (вы можете проверить это самостоятельно, напечатав response.body
в методе parse()
): 'downloader/response_bytes': 101351
.
Проблема в том, как вы анализируете ответ. Вы используете селекторы CSS (например, response.css('.title.may-blank::text')
), которые ничего не возвращают, потому что в HTML нет элементов с такими классами (проверьте источник веб-страницы в браузере и найдите элементы, которые вы пытаетесь выбирать). На самом деле вы заметите, что Reddit принимает меры против сканирования, назначая неизвестные классы элементам HTML.
Однако при проверке исходного кода оказывается, что конец страницы содержит данные JSON, завернутые в <script id = "data"></script>
, которые включают информацию о сообщениях (заголовок, голоса и т. д.). Информация, которую вы хотите извлечь, структурирована следующим образом:
posts
└── models
└── postId
├── title
├── score
└── created
Вы можете просто загрузить и проанализировать данные JSON, чтобы получить нужные поля. Вот рабочая реализация метода parse()
:
def parse(self, response):
# get the contents inside <script id = "data"></script>
data = response.css('#data::text').get()
# remove anything before { and after } to get valid JSON
data = re.findall(r"{.*}",str(data), re.MULTILINE)[0];
jsonresponse = json.loads(data)
titles = []
votes = []
times = []
for post in jsonresponse["posts"]["models"]:
titles.append(jsonresponse["posts"]["models"][post]["title"])
votes.append(jsonresponse["posts"]["models"][post]["score"])
times.append(jsonresponse["posts"]["models"][post]["created"])
for item in zip(titles,votes,times):
scraped_info = {
'title' : item[0],
'vote' : item[1],
'created_at' : item[2],
}
yield scraped_info
Пример вывода:
[scrapy.core.scraper] DEBUG: Scraped from <200 https://www.reddit.com/r/gameofthrones/>
{'title': '[NO SPOILERS] GoT this viewing party invite today. What do you think?', 'vote': 133, 'created_at': 1554610745000}
Демо: https://repl.it/@glhr/55557800
Спасибо, это правильно. Ошибка связана с отступом, с которым я все еще пытаюсь разобраться. Я взял Python из JS, поэтому не знаю, насколько Python придирчив к отступам.
Я решил отступ, это внешняя проблема. Тем не менее, теперь он видит 200 http, но не сканирует и не выдает сообщений об ошибках, поэтому не знаю, в чем проблема. Я прикрепил отредактированный код и темы выше.
@Thinkerer Я обновил свой ответ рабочей реализацией синтаксического анализа. Вы также можете увидеть вывод в CSV-файле в демоверсии (в файлах слева).
Спасибо за ссылку, очень ценю усилия, чтобы сделать это простым. Ссылка работает. Один вопрос, в какой части кода проверки вы замечаете json? Я пытался искать, но не смог найти. Я добавил .json к URL-адресу и попытался сделать дамп в анализаторе, но не увидел такой четкой иерархии.
Используйте Ctrl+U, чтобы просмотреть полный исходный код и выполнить поиск «данных» (включая двойные кавычки). Обратите внимание, что это огромный блок JSON.
Это странно, я тоже удалил двойную косую черту, но это выдало мне ошибку, что-то в Scrapy. Хорошо, проверим и ответим в ближайшее время, спасибо!