[네트워크 보안을 통해 크롤러를 연습할 수 있습니다 - 100가지 사례] 사례 7: 멀티스레딩 + 작업 대기열 + 상호 배제 잠금

목차

1. 멀티 스레드 분석:

2. 코드 구현

3. 네트워크 보안의 작은 원


1. 멀티 스레드 분석:

멀티스레드 크롤러 패키지의 경우 강력한 멀티스레드 크롤러를 구축하는 데 사용할 수 있는 인기 있는 여러 Python 라이브러리가 있습니다.

구현 기능:
요청 라이브러리를 사용하여 HTTP 요청을 보내고 응답 데이터를 얻습니다.
beautifulsoup4 라이브러리를 사용하여 HTML 또는 XML 응답 콘텐츠를 구문 분석합니다.
threading 모듈을 사용하여 스레드를 만들고 관리합니다.
대기열 모듈을 사용하여 크롤링할 URL을 저장하기 위한 작업 대기열을 만듭니다.
데이터 경쟁을 피하기 위해 스레드 동기화에 뮤텍스(잠금)를 사용합니다.

샘플 코드:

import requests
from bs4 import BeautifulSoup
import threading
from queue import Queue

# 创建任务队列
url_queue = Queue()

# 设置要爬取的URL列表
urls = ['http://example.com/page1', 'http://example.com/page2', 'http://example.com/page3']

# 将URL加入任务队列
for url in urls:
    url_queue.put(url)

# 互斥锁
lock = threading.Lock()

# 爬取函数
def crawl():
    while True:
        # 从队列中获取URL
        url = url_queue.get()
        
        # 发送HTTP请求
        response = requests.get(url)
        
        # 解析HTML响应
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 在这里进行你需要的数据提取和处理操作
        # ...

        # 使用互斥锁输出结果
        with lock:
            print(f"URL: {url}, Data: {data}")
        
        # 标记任务完成
        url_queue.task_done()

# 创建并启动多个线程
num_threads = 4  # 设置线程数量

for _ in range(num_threads):
    t = threading.Thread(target=crawl)
    t.daemon = True  # 设置为守护线程
    t.start()

# 阻塞,直到队列中的所有任务完成
url_queue.join()

위의 코드는 여러 스레드가 있는 크롤러를 만들고 각 스레드는 작업 대기열에서 URL을 가져와 크롤링 작업을 수행합니다. 실제 사용 시 예외 처리 추가, 적절한 수의 스레드 설정 등 실제 상황에 따라 적절한 수정 및 최적화가 필요할 수 있습니다.
 



2. 코드 구현

연산 결과

크롤링이 완료된 후 멀티 스레드이기 때문에 크롤링된 페이지 수가 순서대로 표시되지 않는 것을 볼 수 있습니다.

단일 계정/IP 멀티스레딩의 결과

목표 1: 객체 잠금 생성

정의된 위치는 리소스를 운영할 때 이 잠금을 사용할 수 있도록 합니다.

csv_lock = threading.Lock()

스레드 잠금 개체를 만듭니다 csv_lock. 스레드 잠금은 경합 상태를 피하기 위해 한 번에 하나의 스레드만 리소스에 액세스할 수 있도록 공유 리소스를 보호하는 데 사용됩니다.


목표 2: 리소스를 조작하면서 리소스 잠금 구현

객체 조작 전후에 잠금 및 해제 구현

        csv_lock.acquire()
        csv_w.writerow((title.strip(), link, type_texts, money, email, phone))
        csv_lock.release()

(1) csv_lock.acquire(): 현재 스레드가 공유 리소스에서 작동하기 시작하고 다른 스레드가 대기해야 함을 의미하는 스레드 잠금을 가져옵니다.

(2) csv_w.writerow((title.strip(), link, type_texts, money, email, phone)): 공유 리소스에서 작동하기 위해 CSV 파일에 데이터 행을 씁니다. csv_wCSV 작성기 객체이고, writerow()메서드는 데이터 행을 쓰는 데 사용되며 매개변수는 튜플이며 튜플의 각 요소는 데이터 열에 해당합니다.

(3) csv_lock.release(): 현재 스레드가 공유 리소스에 대한 작업을 완료하고 다른 스레드가 잠금을 획득하기 위해 계속 경쟁할 수 있음을 나타내는 스레드 잠금을 해제합니다.


목표 3: 멀티스레딩 구현

    threads = []
    for page in range(1, 5):
        thread = threading.Thread(target=crawl_page, args=(page,))
        threads.append(thread)
        thread.start()

    for thread in threads:
        thread.join()

(1) 스레드 = []: 생성된 스레드 객체를 저장할 빈 목록 스레드를 생성합니다.

(2) for page in range(1, 5):: 루프 반복을 통해 페이지는 크롤링할 페이지 번호를 나타내는 1, 2, 3, 4 값을 순서대로 취합니다. 여기서는 4페이지의 콘텐츠가 크롤링된다고 가정합니다.

(3) thread = threading.Thread(target=crawl_page, args=(page,)): 스레드 객체 thread를 생성하고, crawl_page로 실행할 함수를 지정하고, 파라미터 페이지에 전달합니다.

(4) Threads.append(thread): 생성된 스레드 객체 스레드를 후속 작업을 위해 목록 스레드에 추가합니다.

(5) thread.start(): crawl_page 함수 실행을 시작하도록 스레드를 시작합니다.

(6) 스레드 내의 스레드:: 목록 스레드의 스레드 개체를 통해 반복합니다.

(7) thread.join(): 스레드 객체의 join() 메서드를 호출하여 메인 스레드가 스레드가 실행을 완료할 때까지 대기하도록 합니다. 이렇게 하면 후속 코드를 계속 실행하기 전에 모든 스레드가 실행됩니다.


암호:

참고: 자신의 쿠키를 입력하십시오.

(쿠키를 채우지 않으면 크롤링될 가능성이 있습니다)

import time
import requests
import csv
from bs4 import BeautifulSoup
import threading

def get_page(url):
    try:
        headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36',
            'Cookie':'!!!!!!!!!!!!!'
        }

        response = requests.get(url, headers=headers, timeout=10)
        return response.text
    except:
        return ""

def get_TYC_info(page):
    TYC_url = f"https://www.tianyancha.com/search?key=&sessionNo=1688538554.71584711&base=hub&cacheCode=00420100V2020&city=wuhan&pageNum={page}"
    html = get_page(TYC_url)

    soup = BeautifulSoup(html, 'lxml')
    GS_list = soup.find('div', attrs={'class': 'index_list-wrap___axcs'})
    GS_items = GS_list.find_all('div', attrs={'class': 'index_search-box__7YVh6'})

    for item in GS_items:
        title = item.find('div', attrs={'class': 'index_name__qEdWi'}).a.span.text
        link = item.a['href']
        company_type_div = item.find('div', attrs={'class': 'index_tag-list__wePh_'})

        if company_type_div is not None:
            company_type = company_type_div.find_all('div', attrs={'class': 'index_tag-common__edIee'})
            type_texts = [element.text for element in company_type]
        else:
            type_texts = ''

        money = item.find('div', attrs={'class': 'index_info-col__UVcZb index_narrow__QeZfV'}).span.text

        for u in [link]:
            html2 = get_page(u)
            soup2 = BeautifulSoup(html2, 'lxml')
            email_phone_div = soup2.find('div', attrs={'class': 'index_detail__JSmQM'})

            if email_phone_div is not None:
                phone_div = email_phone_div.find('div', attrs={'class': 'index_first__3b_pm'})
                email_div = email_phone_div.find('div', attrs={'class': 'index_second__rX915'})

                if phone_div is not None:
                    phone_element = phone_div.find('span', attrs={'class': 'link-hover-click'})
                    if phone_element is not None:
                        phone = phone_element.find('span',attrs={'class':'index_detail-tel__fgpsE'}).text
                    else:
                        phone = ''
                else:
                    phone = ''

                if email_div is not None:
                    email_element = email_div.find('span', attrs={'class': 'index_detail-email__B_1Tq'})
                    if email_element is not None:
                        email = email_element.text
                    else:
                        email = ''
                else:
                    email = ''
            else:
                phone = ''
                email = ''

            csv_lock.acquire()
            csv_w.writerow((title.strip(), link, type_texts, money, email, phone))
            csv_lock.release()

def crawl_page(page):
    get_TYC_info(page)
    print(f'第{page}页已爬完')

if __name__ == '__main__':
    with open('5.csv', 'a', encoding='utf-8', newline='') as f:
        csv_w = csv.writer(f)
        csv_w.writerow(('公司名', 'URL', '类型', '资金', '电子邮件', '电话号码'))

        csv_lock = threading.Lock()

        threads = []
        for page in range(1, 5):
            thread = threading.Thread(target=crawl_page, args=(page,))
            threads.append(thread)
            thread.start()

        for thread in threads:
            thread.join()

        time.sleep(2)



3. 네트워크 보안의 작은 원

README.md Book Bansheng/Network Security Knowledge System-Practice Center-Code Cloud-Open Source China(gitee.com) https://gitee.com/shubansheng/Treasure_knowledge/blob/master/README.md

GitHub - BLACKxZONE/Treasure_knowledge https://github.com/BLACKxZONE/Treasure_knowledge

Supongo que te gusta

Origin blog.csdn.net/qq_53079406/article/details/131581786
Recomendado
Clasificación