Очистка веб-данных (комментарии к новостям в интернете) с помощью Scrapy (Python)
Я хочу соскрести данные веб-комментариев из онлайн-новостей исключительно для исследования. И я заметила, что мне нужно узнать о Скрэпи...
Обычно я программирую на Python. Я думал, что это будет легко узнать. Но у меня возникли некоторые проблемы.
Я хочу наскрести комментарий к новостямhttp://news.yahoo.com/congress-wary--but-unlikely-to-blow-up-obama-s-iran-deal-230545228.html.
Но проблема в том, что есть кнопка (>просмотреть комментарии (452)), чтобы увидеть комментарии. Кроме того, что я хочу сделать, так это соскрести все комментарии в этой новости. К сожалению, мне нужно нажать другую кнопку (Просмотреть больше комментариев), чтобы увидеть еще 10 комментариев.
Как я могу справиться с этой проблемой?
Код, который я сделал, выглядит следующим образом. Извините за слишком плохой код.
#############################################
from scrapy.spider import BaseSpider
from scrapy.selector import Selector
from tutorial.items import DmozItem
class DmozSpider(BaseSpider):
name = "dmoz"
allowed_domains = ["news.yahoo.com"]
start_urls = ["http://news.yahoo.com/blogs/oddnews/driver-offended-by-%E2%80%9Cwh0-r8x%E2`%80%9D-license-plate-221720503.html",]
def parse(self, response):
sel = Selector(response)
sites = sel.xpath('//div/p')
items = []
for site in sites:
item = DmozItem()
item['title'] = site.xpath('/text()').extract()
items.append(item)
return items
Вы видите, как много еще предстоит сделать, чтобы решить мою проблему. Но мне нужно спешить.. Я все равно сделаю все, что в моих силах.
2 ответов:
Поскольку вы похожи на тип "сначала попробуйте задать вопрос позже" (это очень хорошо), я не дам вам ответ, но (очень подробное) руководство о том, как найти ответ.
Дело в том, что если вы не являетесь разработчиком yahoo, у вас, вероятно, нет доступа к исходному коду, который вы пытаетесь наскрести. То есть вы не знаете точно, как построен сайт и как ваши запросы к нему как пользователю обрабатываются на стороне сервера. Однако вы можете исследовать клиентскую сторону и попытайтесь подражать ему. Мне нравится использовать для этого инструменты разработчика Chrome, но вы можете использовать и другие, такие как FF firebug. Итак, прежде всего нам нужно выяснить, что происходит. Итак, как это работает, вы нажимаете на "показать комментарии", он загружает первые десять, затем вам нужно продолжать нажимать на следующие десять комментариев каждый раз. Обратите внимание, однако, что все это нажатие не приведет вас к другой ссылке, но оживленно извлекает комментарии, что является очень аккуратным пользовательским интерфейсом, но в нашем случае требует немного больше работа. Я могу сразу сказать две вещи:
- они используют javascript для загрузки комментариев (потому что я остаюсь на той же странице).
- они загружают их динамически с помощью AJAX-вызовов каждый раз, когда вы нажимаете (это означает, что вместо загрузки комментариев со страницы и просто показа их вам, с каждым щелчком он делает еще один запрос к базе данных).
Теперь давайте щелкнем правой кнопкой мыши и проверим элемент на этой кнопке. Это на самом деле просто простой промежуток с текст:
<span>View Comments (2077)</span>Глядя на это, мы все еще не знаем, как это генерируется или что он делает при нажатии. Хорошо. Теперь, держа окно devtools открытым, давайте щелкнем по нему. Это открыло первую десятку. Но на самом деле нам было предложено забрать их. Запрос, который записал chrome devtools. Мы смотрим на вкладку "Сеть" в инструментах разработчика и увидеть много противоречивых данных. Подождите, вот один, который имеет смысл:
http://news.yahoo.com/_xhr/contentcomments/get_comments/?content_id=42f7f6e0-7bae-33d3-aa1d-3dfc7fb5cdfc&_device=full&count=10&sortBy=highestRated&isNext=true&offset=20&pageNumber=2&_media.modules.content_comments.switches._enable_view_others=1&_media.modules.content_comments.switches._enable_mutecommenter=1&enable_collapsed_comment=1Видите? _xhr и затем get_comments. Что делает много смысла. Переход по этой ссылке в браузере дал мне объект JSON (похожий на словарь python), содержащий все десять комментариев, которые получил этот запрос. Теперь это запрос, который вам нужно эмулировать, потому что это тот, который дает вам то, что вы хотите. Сначала давайте переведем это на какой-нибудь нормальный reqest, который человек может прочитать:
Теперь это просто вопрос проб и ошибок. Однако здесь следует отметить несколько моментов:go to this url: http://news.yahoo.com/_xhr/contentcomments/get_comments/ include these parameters: {'_device': 'full', '_media.modules.content_comments.switches._enable_mutecommenter': '1', '_media.modules.content_comments.switches._enable_view_others': '1', 'content_id': '42f7f6e0-7bae-33d3-aa1d-3dfc7fb5cdfc', 'count': '10', 'enable_collapsed_comment': '1', 'isNext': 'true', 'offset': '20', 'pageNumber': '2', 'sortBy': 'highestRated'}Как вы можете видеть, это потребует некоторой работы, но, несмотря на все, что я написал, это не очень сложная задача.
Очевидно, что граф-это то, что решает, сколько комментариев вы получите. Я попытался изменить его на 100, чтобы посмотреть, что произойдет, и получил плохой запрос. И это было достаточно мило, чтобы сказать мне, почему - "смещение должно быть кратно общему числу строк". Итак, теперь мы понимаем, как использовать offset
Content_id, вероятно, является чем-то, что идентифицирует статью, которую Вы читаете. Это означает, что вам нужно как-то извлечь это из исходной страницы. Попробуйте немного покопаться, и вы найдете его.
Кроме того, вы, очевидно, не хотите чтобы получить 10 комментариев одновременно, поэтому, вероятно, неплохо найти способ каким-то образом получить общее количество комментариев (либо узнать, как страница получает его, либо просто получить его из самой статьи)
С помощью devtools вы получаете доступ ко всем клиентским скриптам. Таким образом, копая вы можете обнаружить, что эта ссылка на /get_comments / хранится в объекте javascript с именем YUI. Затем вы можете попытаться понять, как он делает запрос, и попытаться подражать этому (хотя вы возможно, вы сами сможете это понять)
Возможно, вам придется преодолеть некоторые меры безопасности. Например, для доступа к комментариям может потребоваться сеансовый ключ из исходной статьи. Это используется для предотвращения прямого доступа к некоторым частям сайтов. Я не буду утруждать вас подробностями, потому что в данном случае это не кажется проблемой, но вы должны знать об этом на случай, если это обнаружится.
Наконец, вам придется разобрать объект JSON (python имеет отличные встроенные инструменты для этого), а затем проанализировать HTML-комментарии, которые вы получаете (для которых вы можете проверить BeautifulSoup).
Так что не паникуйте.
Это просто вопрос копания и копания, пока вы не найдете золото (кроме того, наличие некоторых базовых знаний в Интернете не повредит). Затем, если вы столкнулись с блокпостом и действительно не могу идти дальше, вернуться сюда, чтобы так, и спросить снова. Кто-нибудь вам поможет.
Удачи!
Я благодарен за этот вопрос, так как он заставил меня начать пытаться очистить комментарии yahoo, и я просто хотел добавить обновление, потому что yahoo изменила способ обработки комментариев с тех пор, как этот вопрос был опубликован. Во-первых, есть 3 URL-адреса, представляющие интерес, в зависимости от того, что вы хотите получить. С их помощью вы можете получить основные потоки комментариев, ответы на поток или комментарии от пользователя. Это
urlComments = 'https://www.yahoo.com/news/_td/api/resource/canvass.getMessageListForContext_ns;context=%1s;count=10;index=%1s;lang=en-US;namespace=yahoo_content;oauthConsumerKey=frontpage.oauth.canvassKey;oauthConsumerSecret=frontpage.oauth.canvassSecret;rankingProfile=canvassHalfLifeDecayProfile;region=US;sortBy=popular;type=null;userActivity=true' urlReply = 'https://www.yahoo.com/news/_td/api/resource/canvass.getReplies_ns;context=%1s;count=10;index=%1s;lang=en-US;messageId=%1s;namespace=yahoo_content;oauthConsumerKey=frontpage.oauth.canvassKey;oauthConsumerSecret=frontpage.oauth.canvassSecret;region=US;sortBy=createdAt;tags=' urlUser = 'https://www.yahoo.com/news/_td/api/resource/canvass.getUserMessageHistory;count=10;index=%1s;lang=en-US;oauthConsumerKey=frontpage.oauth.canvassKey;oauthConsumerSecret=frontpage.oauth.canvassSecret;region=US;sortBy=createdAt;userId=%1s'Теперь я вставил пару
%1sв URL-адреса, чтобы вставить нужные переменные в URL-адрес, например идентификатор статьи, индекс или идентификатор пользователя. Как и прежде, требуется несколько параметров:params = {'bkt': ["news-d-202","newsdmcntr"], 'device': 'desktop', 'feature': 'cacheContentCanvas,videoDocking,newContentAttribution,livecoverage,featurebar,deferModalCluster,specRetry,newLayout,sidepic,canvassOffnet,ntkFilmstrip,autoNotif,CanvassTags', 'intl': 'us', 'lang': 'en-US', 'partner': 'none', 'prid': '5t11qvhclanab', 'region': 'US', 'site': 'fp', 'tz': 'America/PICKACITY', <-- insert a city 'ver': '2.0.7765', 'returnMeta': 'true'}Используя библиотеку
requests, мы можем вытаскивать комментарии, например.response = requests.get(u, params=params) #u is a url from above coms = response.json()['data']['canvassMessages'] #drop the ['canvassMessages'] if you want to get replies to a threadОттуда вы можете вытащить все, что хотите из комментария. Теперь,
comsбудет иметь только 10 комментариев в нем (если вы посмотрите на URL, вы увидитеcount=10- к сожалению, Макс, кажется, 30). Чтобы получить следующий набор из 10, вставьте значениеcoms[-1]['index']в нужный URL-адрес и возьмите следующие 10. Однако проблема, с которой я столкнулся, заключается в том, что вы можете захватить только около 1000 комментариев, прежде чем yahoo отключится. Например, если вы посетите эту страницу комментариев , вы увидите комментарии 1000-1009 (найдите значение "индекс", и вы получите что-то вродеv=1:s=popular:sl=1498836633:off=1000). Но если вы посетите эту следующую страницу комментариев , вы увидите комментарии 1010-1019, но на самом деле комментарии не загружаются. Это довольно раздражает, и если кто-то знает о том, как преодолеть эту проблему, я был бы весьма рад этому. решение. Наконец, чтобы получить идентификатор статьи, откройте источник страницы и выполните поиск"pstaid", а затем скопируйте значение, которое следует за ним. Например, приведенные выше ссылки предназначены для комментариев из этой статьи с большим количеством комментариев. Если вы ищете"pstaid", вы находите значение0efc85df-eb0b-373e-b6f3-4c513ed2a415, и это идентификатор статьи, который вы вставляете в URL.
Comments