Эта проблема не имеет ничего общего с вашей реализацией кода, это просто опечатка в 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