Применение базовой многопоточности для веб-скрейпинга в bs4


Обзор

  • в этом блоге мы рассмотрим простой пример использования многопоточности для веб-скрейпинга в python
  • Требования
  • библиотеки, используемые в данном проекте
beautifulsoup4==4.11.1  
requests==2.28.1 
urllib3==1.26.10
Войдите в полноэкранный режим Выход из полноэкранного режима

Синтаксис

  • создание потока с помощью класса Thread
 Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None) 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • мы не будем создавать пользовательский поток, а воспользуемся этим классом и будем использовать только параметры target, который указывает на функцию, где мы будем применять поток, и параметр args, так как мы будем передавать аргументы в функцию
  • направление запросов на веб-сайт
 response = requests.get(url) 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • установка таймера между запросами, где n — число float или int
 time.sleep(n)
Войдите в полноэкранный режим Выход из полноэкранного режима
  • создание нашего супа
soup = BeautifulSoup(response.text,'html.parser') 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • поиск селекторов
selector_padre = soup.find('selector',{'class: nombre-de-clase'}) 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • эта функция вернет первый найденный селектор с указанным именем класса
  • если наш селектор содержится в родительском селекторе, мы можем продолжать его искать
  • в данном случае мы ищем все селекторы с именем selector-child
 .find_all('selector-hijo') 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • получение содержимого селектора
 .find('title').text 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • создание json
with open("output.json", "a") as f:
    json.dump(data, f, indent=4) 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • важно, чтобы при открытии файла с помощью контекстного менеджера мы перевели его в режим добавления, иначе мы не будем иметь полных результатов, поскольку каждый поток будет переписывать его.
  • получение названия потока
 current_thread().getName() 
Войдите в полноэкранный режим Выход из полноэкранного режима

Пример

  • в этом примере мы собираемся сделать веб-скрейпинг новостного сайта мы сделаем запрос на главную страницу и введем ссылки на категории новостей мы введем категории через потоки, каждый поток будет иметь часть этих ссылок имея 3 потока в общей сложности.
  • импортируйте необходимые библиотеки
from bs4 import BeautifulSoup
import requests 
from threading import Thread
from threading import current_thread
import time 
import json
Войдите в полноэкранный режим Выход из полноэкранного режима

main: в нашем методе main будет находиться весь код, в нашем скрипте мы не будем обращаться непосредственно к этой функции, а будем делать это через потоки.

def main(x,y):
    url = "https://pagina12.com.ar/"
    bts = requests.get(url)
    soup = BeautifulSoup(bts.text, 'html.parser')
    urls = soup.find("div", {"class": "p12-dropdown-column"}).find_all('a', href=True)
    for link in urls[x:y]:
        r = requests.get(link.get('href'))
        time.sleep(1)
        s = BeautifulSoup(r.text, 'html.parser')
        title = s.find("title").text
        with open("links4.json", "a") as f:
            json.dump({'title':title,'thread': current_thread().getName()}, f, indent=4)

Войдите в полноэкранный режим Выход из полноэкранного режима
  • главная функция получает два параметра x и y, которые будут использоваться для передачи их в качестве индекса в список урлов.
    • первое, что мы имеем внутри основной функции — это url сайта, на котором мы хотим провести веб-скрепинг
    • мы делаем запрос к этому url и помещаем его в переменную response
    • мы создаем наш «суп», передавая Beautifulsoup файл response.text и парсер, в данном случае html.parser
    • мы продолжаем получать урлы, ищем селектор div с классом p12-dropdown-columns на этом div мы ищем все его дочерние селекторы anchors или ‘a’ это вернет список этих селекторов (только из a)
    • мы проходим по списку урлов по частям с позициями индексов от x до y, проходя по урлам таким образом, мы можем заставить поток, который проходит через этот цикл, нести свою собственную «порцию» ссылок, и таким образом, когда мы генерируем json, у нас не будет повторяющихся элементов.
    • внутри цикла мы сделаем запрос с этими ссылками
    • мы ставим таймер после каждого запроса
    • мы заново создаем наш суп
    • для каждого сайта мы собираемся получить название страницы, которую мы ищем с помощью .find(), и получить содержимое найденного селектора с помощью .text
    • мы открываем json с помощью контекстного менеджера в режиме добавления, чтобы избежать перезаписи json
    • В json.dump мы передаем данные, которые нам нужны, затем имя, которое мы дали объекту файла, и ставим идентификатор из 4 пробелов.

потоки: запуск потоков вне основной функции

t1 = Thread(target=main, args=(0,10))
t2 = Thread(target=main, args=(10,20))
t3 = Thread(target=main, args=(20,25))
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
print("Done!") 
Войдите в полноэкранный режим Выход из полноэкранного режима
  • создать потоки путем инстанцирования класса Thread(…)
  • запускаем поток с помощью t.start()
  • завершите его с помощью t.join()

Оцените статью
devanswers.ru
Добавить комментарий