CoderCastrov logo
CoderCastrov
Веб-парсер

Извлечение данных с Medium.com Часть 2 - подготовка данных

Извлечение данных с Medium.com Часть 2 - подготовка данных
просмотров
2 мин чтение
#Веб-парсер
Table Of Content

    В этом посте я объясню, где найти исходные данные и как выглядит запрос для начала парсинга.

    На medium есть страница с списком тем, которая очень хорошо оформлена:

    Однако ссылки на все темы не захардкожены в HTML, они являются частью кода JavaScript. В коде есть некоторый шум, но после фильтрации получается следующий список:

    "искусство",
    "красота",
    "книги",
    "комиксы",
    "культура",..., "транспорт", "женщины", "мир"

    В списке около 100 тем. Я думаю, что на Medium есть гораздо больше 100 тем, но они выбрали эти 100 как наиболее репрезентативные или наиболее популярные. Так что, если парсинг основан только на этом списке, то он может быть неполным, но должен включать большинство статей.


    Хорошо, достаточно говорить, давайте перейдем к коду. Я использую scrapy, не потому что я привык к нему, а просто потому что недавно изучал его и хотел попробовать. В качестве базы данных используется MongoDB, библиотека pymongo очень проста в использовании.

    Сначала напишем простую функцию для генерации данных запроса:

    topic_query = "query TopicHandler($topicSlug: ID!, 
    ...
    PostPresentationTracker_post  __typename}"
    def generateData(self, to_time, topic_name):
        return {
            "operationName": "TopicHandler",
            "variables": {"topicSlug": topic_name, "feedPagingOptions": {"limit": 25, "to": to_time}},
            "query": self.topic_query
        }

    Запрос можно легко найти в сетевом API-вызове, поэтому здесь запрос является просто заполнителем.


    Шаг 2, фактическая функция парсинга:

    def parse(self, response):
        if "graphql" in response.request.url:
            p = json.loads(response.body)
            # получаем временную метку из ответа и продолжаем
            page_info = p['data']['topic']['latestPosts']['pagingInfo']['next']
    
        my_data = self.generateData(to_time, self.topic_list[topic_index])
        yield scrapy.Request("https://medium.com/_/graphql", method='POST',
                             body=json.dumps(my_data),
                             headers={'Content-Type': 'application/json'})
        pass

    Здесь делается очень грубая работа. Если URL содержит "graphql" в запросе, то парсим ответ и находим все содержимое, если нет, то просто запускаем его с темой и используем текущую временную метку в качестве стартовой точки.

    Чтобы не перегружать сервер Medium, я делаю по одной теме за раз и продолжаю до тех пор, пока у этой темы нет поля "Next" для запроса, затем перехожу к следующей теме.

    Прежде чем перейти к результатам, можно улучшить несколько вещей для повышения эффективности:

    Но на данный момент этого уже достаточно для проекта на выходные. Посмотрите следующий пост для результатов.

    Последняя статья содержит все полученные до сих пор числа, пожалуйста, проверьте здесь!