【网络安全带你练爬虫-100练】第7练:多线程+任务列+互斥锁

目录

一、多线程分析:

二、代码实现

三、网络安全小圈子


一、多线程分析:

当涉及到多线程爬虫数据包时,有几个流行的Python库可以用来构建强大的多线程爬虫。

实现功能:
使用requests库发送HTTP请求并获取响应数据。
使用beautifulsoup4库解析HTML或XML响应内容。
使用threading模块创建和管理线程。
使用queue模块创建任务队列,用于存储待爬取的URL。
使用互斥锁 (Lock) 进行线程同步,避免数据竞争。

示例代码:

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并进行爬取操作。注意,在实际使用中,您可能需要根据实际情况进行适当的修改和优化,比如添加异常处理、设置合理的线程数量等。
 

扫描二维码关注公众号,回复: 15728368 查看本文章


二、代码实现

运行结果

爬取完成,可以看见爬取的页数也不是按照顺序来的,因为他是多线程

单账号/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_w是一个CSV写入器对象,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)threads = []:创建一个空列表threads,用于存放创建的线程对象

(2)for page in range(1, 5)::通过循环迭代,page依次取值为1、2、3、4,表示要爬取的页码。这里假设要爬取4页的内容。

(3)thread = threading.Thread(target=crawl_page, args=(page,)):创建一个线程对象thread,指定要执行的函数为crawl_page,并传入参数page。

(4)threads.append(thread):将创建的线程对象thread添加到列表threads中,用于后续操作。

(5)thread.start():启动线程,使其开始执行crawl_page函数。

(6)for thread in threads::通过循环遍历列表threads中的线程对象。

(7)thread.join():调用线程对象的join()方法,让主线程等待该线程执行完毕。这样可以确保所有线程都执行完毕后再继续执行后续的代码


代码实现:

注:填上自己的cookie

(不填cookie有一定的机会可能爬到)

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)



三、网络安全小圈子

README.md · 书半生/网络安全知识体系-实战中心 - 码云 - 开源中国 (gitee.com)https://gitee.com/shubansheng/Treasure_knowledge/blob/master/README.md

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

猜你喜欢

转载自blog.csdn.net/qq_53079406/article/details/131581786