说到数据爬取,大部分人都会想到使用Scrapy工具,但是仅仅停留在会使用的阶段。但是要真正的成为技术大牛,需要学会更多的爬虫技术,对于爬虫来说突破各种网站的反爬机制也是需要技术能力的。所以今天为了增加对目标网站爬虫机制的理解,我们可以通过手动实现多线程的爬虫过程,同时,引入IP代理池进行基本的反爬操作。 本次使用腾讯新闻网进行爬虫,该网站具有反爬机制,同时数量足够大,多线程效果较为明显。 需要使用到的技术如下 分析完目标网站的网的数据后,搭建IP代理池,用于反爬作用。由于使用的代理商提供了参考demo,所以本代码里面直接使用的是代理商提供的代码。搭建完IP代理池后,我们开始着手多线程爬取数据的工作。一旦使用多线程,则需要考虑到数据的读写顺序问题。这里使用python中的队列queue进行存储新闻代码,不同线程分别从这个queue中获取新闻代码,并访问指定新闻的数据。由于queue的读取和写入是阻塞的,所以可以确保该过程不会出现读取重复和读取丢失新闻代码的,实现过程如下: - import asyncio
- import aiohttp
- import threading
- from collections import Counter
- # 定义一个全局变量,用于存储分类结果
- categories = Counter()
- # 定义一个函数,用于根据文本内容进行分类
- def classify(text):
- # 这里可以使用任何文本分类的方法,例如正则表达式、机器学习等
- # 这里为了简单起见,只使用了简单的字符串匹配
- if "Python" in text:
- return "Python"
- elif "Java" in text:
- return "Java"
- elif "C++" in text:
- return "C++"
- else:
- return "Other"
- async def fetch_page(url, proxy):
- # 创建一个 aiohttp 的 ClientSession 对象,并指定代理IP和端口
- async with aiohttp.ClientSession(proxy=proxy) as session:
- # 使用 session.get 方法发送请求,并获取响应对象
- async with session.get(url) as response:
- # 返回响应的文本内容
- return await response.text()
- async def main():
- urls = ["https://www.baidu.com/s?wd=" + str(i) for i in range(10)] # 生成十个百度搜索网址
-
- # 假设有一个文件 16yun.txt,每行存储一个代理host和端口,例如 it帮论坛真好:3333
- # 读取文件中的所有代理,并存储在一个列表中
- with open("16yun.txt") as f:
- proxies = [line.strip() for line in f]
-
- tasks = [] # 创建一个空列表,用于存储 task 对象
-
- # 遍历 urls 和 proxies 列表,为每个 url 配对一个 proxy,并创建 task 对象
- for url, proxy in zip(urls, proxies):
- task = asyncio.create_task(fetch_page(url, proxy))
- tasks.append(task)
-
- results = await asyncio.gather(*tasks) # 同时运行所有 task 并获取结果
-
- # 创建一个线程池,用于执行分类任务
- pool = threading.ThreadPoolExecutor(max_workers=4)
-
- for result in results:
- print(result[:100]) # 打印每个网页的前 100 个字符
-
- # 使用线程池提交一个分类任务,并更新全局变量 categories
- category = pool.submit(classify, result).result()
- categories[category] += 1
-
- # 关闭线程池并等待所有任务完成
- pool.shutdown(wait=True)
-
- # 打印最终的分类结果
- print(categories)
- asyncio.run(main()) # 运行主协程
复制代码
|