利用python进行多线程爬虫
import threading import time import requests import json from queue import Queue from lxml import etree class CrawlThread(threading.Thread): '''doc string for crawl thread''' def __init__(self, name, page_queue, data_queue): super(CrawlThread, self).__init__() self.name = name self.page_queue = page_queue self.data_queue = data_queue self.url = 'http://www.ifanjian.net/latest-{}' self.headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36", } def run(self): print('%s ------- 线程启动' % self.name) while True: # 判断采集线程何时结束 if self.page_queue.empty(): break # 从队列中取出页面 page = self.page_queue.get() print("===采集===开始第%s页数据" % page) # 拼接url,发送请求 url = self.url.format(page) time.sleep(1) r = requests.get(url, headers=self.headers) # 将响应内容存放到data_queue self.data_queue.put({ "index": str(page), "text": r.text }) print("===采集===结束第%s页数据" % page) print('%s ------- 线程结束' % self.name) class ParserThread(threading.Thread): '''doc string for parse thread''' def __init__(self, name, data_queue, fp, lock): super(ParserThread, self).__init__() self.name = name self.data_queue = data_queue self.fp = fp self.lock = lock def run(self): print('%s ------- 线程启动' % self.name) while True: try: # 从data_queue中取出数据 data = self.data_queue.get(True, 10) print("===解析===开始第%s页数据" % data["index"]) # 解析内容 self.parse_content(data['text']) print("===解析===开始第%s页数据" % data["index"]) except Exception: break print('%s ------- 线程结束' % self.name) # 解析内容 def parse_content(self, data): tree = etree.HTML(data) # 先找出所有的li,然后再从li中找到所有的标题和图片 li_list = tree.xpath("//ul[@class='cont-list']/li") items = [] for li in li_list: # 获取标题 title = li.xpath(".//h2[@class='cont-list-title']/a/text()")[0] # 获取图片 img_url = li.xpath( ".//div[contains(@class,'cont-list-main')]//img/@data-src") item = { '标题': title, '图片链接': img_url } items.append(item) # 写到文件中 self.lock.acquire() self.fp.write(json.dumps(items, ensure_ascii=False) + '\n') self.lock.release() # 用来存放采集线程 g_crawl_list = [] # 用来存放解析线程 g_parser_list = [] def create_crawl_thread(page_queue, data_queue): crawl_names = ['采集线程1', '采集线程2', '采集线程3'] for name in crawl_names: tcrawl = CrawlThread(name, page_queue, data_queue) g_crawl_list.append(tcrawl) def create_parser_thread(data_queue, fp, lock): parse_names = ['解析线程1', '解析线程2', '解析线程3'] for name in parse_names: tparse = ParserThread(name, data_queue, fp, lock) g_parser_list.append(tparse) def create_queue(): page_queue = Queue() for page in range(1, 10): page_queue.put(page) data_queue = Queue() return page_queue, data_queue def main(): # 创建队列 page_queue, data_queue = create_queue() # 打开文件 fp = open('jian.json', 'a', encoding='utf-8') # 创建锁 lock = threading.Lock() # 创建采集线程 create_crawl_thread(page_queue, data_queue) # 创建解析线程 create_parser_thread(data_queue, fp, lock) # 启动所有采集线程 for tcrawl in g_crawl_list: tcrawl.start() # 启动所有解析线程 for tparser in g_parser_list: tparser.start() # 主线程等待子线程结束 for tcrawl in g_crawl_list: tcrawl.join() for tparser in g_parser_list: tparser.join() # 关闭文件 fp.close() print("主线程和子线程全部结束.....") if __name__ == "__main__": main()
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· C# 13 中的新增功能实操
· Supergateway:MCP服务器的远程调试与集成工具
· Vue3封装支持Base64导出的电子签名组件