Извлечение/очистка данных с нескольких/динамических страниц (доступных с базовым URL-адресом и параметром запроса) через цикл с использованием запросов

#python #web-scraping #python-requests

Вопрос:

Поэтому я пытался соскрести некоторые данные с веб-сайта в качестве практики, чтобы отточить свои навыки работы на python. Страница содержит список карточек, содержащих сведения о компании (кажется, 50 на страницу), и навигацию ниже, которая указывает на базовый URL параметры номера страницы, такие как https://clutch.co/uk/app-developers?page=3

Я застрял в точке, где, если я создаю новые запросы для каждого URL-адреса (базовый URL-адрес номер страницы параметры) и получить данные, используя несколько (должность) просит данные извлекаются правильно (new data for each url just as I wanted) , но когда я положил эти шаги в цикле, (generating the url through for loop and params) я получаю результат только на первой странице (хотя результаты повторяются в течение времени, указанного в курсе).

Вот код, который я попробовал с двумя разными результатами:

 #Base code for the project 

import requests
from bs4 import BeautifulSoup as bs

base_url = 'https://clutch.co/uk/app-developers?page='
urls = [base_url   str(x) for x in range(0, 21)]
s = requests.Session()

#Function to extract link href from each element in bs4 object
def get_profile_link(profile_links, profiles=[]):
    for link in profile_links:
        profiles.append(link['href'])
    return profiles
 

Метод 1: Это работает и дает мне данные с 2 страниц (100 результатов без проверки)

 r1 = s.post(urls[0])
soup1 = bs(r1.content)
links1 = soup1.find_all('a', attrs={'data-link_text': "Profile Button"})
list1 = get_profile_link(links1)

r2 = s.post(urls[1])
soup2 = bs(r2.content)
links2 = soup2.find_all('a', attrs={'data-link_text': "Profile Button"})
list2 = get_profile_link(links2, list1)
 

Метод 2: Однако это не работает и дает мне 100 результатов только с 50 уникальными значениями

 #A simplified version of loop to fetch results (I have a slightly complex one that generates url within the loop). 

for x in range(0, 2):
    r = s.post(urls[x])
    soup = bs(r.content)
    links = soup.find_all('a', attrs={'data-link_text': "Profile Button"})
    list = get_profile_link(links)

 

Ищу указания о том, что я делаю неправильно в методе 2, чтобы я мог использовать цикл для извлечения ссылок. Я думаю, что это может сработать с помощью файлов cookie, и я проверил print(r.cookies) , и кажется, что файлы cookie не генерируются/пусты. Я прочитал документы, но не смог понять это ясно.

Пожалуйста, дайте мне знать, если потребуются дополнительные подробности.

Ответ №1:

Рекомендуется не использовать параметры списка по умолчанию в функциях (например profiles=[] ).

Кроме того, не используйте встроенные имена в качестве имен переменных (например list ).

 import requests
from bs4 import BeautifulSoup as bs

# Function to extract link href from each element in bs4 object
def get_profile_link(profile_links):
    rv = []
    for link in profile_links:
        rv.append(link["href"])
    return rv


all_data = []
base_url = "https://clutch.co/uk/app-developers?page="
with requests.session() as s:
    for page in range(0, 2):
        url = base_url   str(page)
        soup = bs(s.post(url).content, "html.parser")
        links = soup.find_all("a", attrs={"data-link_text": "Profile Button"})
        all_data.extend(get_profile_link(links))

print("Length of data:", len(all_data))
print("Unique elements:", len(set(all_data)))
 

С принтами:

 Length of data: 100
Unique elements: 100
 

Комментарии:

1. Я использовал параметры по умолчанию, так как хотел, чтобы функция принимала существующий список и добавляла в него элементы, а не возвращала новый, который мне пришлось бы расширить/объединить/выровнять. Обратите внимание на список, думаю, я бы изменил его при просмотре кода. P.S. Я не мог понять, что я делал неправильно, не могли бы вы уточнить это. Попробую решение, которое вы опубликовали завтра, и увижу окончательный результат. Спасибо.