Сбор коллекций фанатов Bandcamp через POST

Я пытался очистить фан-страницы Bandcamp, чтобы получить список альбомов, которые они купили, и у меня возникают проблемы с эффективностью этого. Я что-то написал с помощью Selenium, но он довольно медленный, поэтому я хотел бы изучить решение, которое, возможно, отправило бы запрос POST на сайт и проанализировало бы JSON оттуда.

Вот образец страницы коллекции: https://bandcamp.com/nhoward

Вот код Selenium:

def scrapeFanCollection(url):
    browser = getBrowser()
    setattr(threadLocal, 'browser', browser)
    #Go to url
    browser.get(url)
    
    try:
        #Click show more button
        browser.find_element_by_class_name('show-more').click()
        
        #Wait two seconds
        time.sleep(2)
        #Scroll to the bottom loading full collection
        scroll(browser, 2)
    except Exception:
        pass
    
    #Return full album collection
    soup_a = BeautifulSoup(browser.page_source, 'lxml', parse_only=SoupStrainer('a', {"class": "item-link"}))
        
    #Empty array
    urls = []
    
    # Looping through all the a elements in the page source
    for item in soup_a.find_all('a', {"class": "item-link"}):
        url = item.get('href')
        if(url != None):
            urls.append(url)
    
    return urls

4 ответа

Доступ к API можно получить следующим образом:

$ curl -X POST -H "Content-Type: Application/JSON" -d \
'{"fan_id":82985,"older_than_token":"1586531374:1498564527:a::","count":10000}' \
https://bandcamp.com/api/fancollection/1/collection_items

Я не встречал сценария, когда "older_than_token" был устаревшим, поэтому проблема сводится к получению "fan_id" учитывая URL-адрес.

Эта информация находится в большом двоичном объекте в id="pagedata" элемент.

>>> import json
>>> import requests
>>> from bs4 import BeautifulSoup
>>> res = requests.get("https://www.bandcamp.com/ggorlen")
>>> soup = BeautifulSoup(res.text, "lxml")
>>> user = json.loads(soup.find(id="pagedata")["data-blob"])
>>> user["fan_data"]["fan_id"]
82985

Собираем все вместе (основываясь на этом ответе):

import json
import requests
from bs4 import BeautifulSoup

fan_page_url = "https://www.bandcamp.com/ggorlen"
collection_items_url = "https://bandcamp.com/api/fancollection/1/collection_items"
res = requests.get(fan_page_url)
soup = BeautifulSoup(res.text, "lxml")
user = json.loads(soup.find(id="pagedata")["data-blob"])

data = {
    "fan_id": user["fan_data"]["fan_id"],
    "older_than_token": user["wishlist_data"]["last_token"],
    "count": 10000,
}
res = requests.post(collection_items_url, json=data)
collection = res.json()

for item in collection["items"][:10]:
    print(item["album_title"], item["item_url"])

я использую user["wishlist_data"]["last_token"] который имеет тот же формат, что и "older_than_token" на всякий случай это имеет значение.

Чтобы получить всю коллекцию, я изменил предыдущий код с

"older_than_token": user["wishlist_data"]["last_token"]к

user["collection_data"]["last_token"]

который содержал правильный токен

Есть несколько разных ответов наolder_than_tokenзначение, но они, похоже, зависят от метаданных конкретной учетной записи. В этой проблеме на GitHub я нашел подсказку , которая, как мне кажется, решает ее: токен, который должен работать для всех, — это"[current unix time]::a::"

например, в большинстве оболочек Mac и Linux вы можете получить текущее значение с помощью:

      $ echo "$(date +%s)::a::"
1700323510::a::

Когда я это делаю, кажется, что все всегда начинается с начала библиотеки, и я могу получить все это одним пакетом.

К сожалению для вас, этот конкретный сайт Bandcamp, похоже, не выполняет никаких вызовов HTTP API для получения списка альбомов. Вы можете проверить это с помощью инструментов разработчика вашего браузера, на вкладке "Сеть" нажмите на фильтр XHR. Похоже, что единственный сделанный вызов - это получение сведений о вашей коллекции.

Другие вопросы по тегам