多线程股吧用户信息爬取

今天分享一些代码,欢迎参考和学习,在上一篇博客的基础上加入了多线程,使得速度提升了十几倍,代码如下:

import csv
import random
import re
import threadingimport chardet
import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
import concurrent.futures
from datetime import datetime
from tqdm import tqdm
from urllib.parse import urljoin
import requestschrome_options = webdriver.ChromeOptions()
# 添加其他选项,如您的用户代理等
# ...
chrome_options.add_argument('--headless')  # 无界面模式,可以加速爬取
# 指定 Chrome WebDriver 的路径
driver = webdriver.Chrome(executable_path='/usr/local/bin/chromedriver', options=chrome_options)
## 浏览器设置选项
# chrome_options = Options()
chrome_options.add_argument('blink-settings=imagesEnabled=false')def get_time():"""获取随机时间"""return round(random.uniform(3, 6), 1)from random import choicedef get_user_agent():"""获取随机用户代理"""user_agents = ["Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",# "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",# "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",# "Mozilla/5.0 (iPod; U; CPU iPhone OS 2_1 like Mac OS X; ja-jp) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5F137 Safari/525.20",# "Mozilla/5.0 (Linux;u;Android 4.2.2;zh-cn;) AppleWebKit/534.46 (KHTML,like Gecko) Version/5.1 Mobile Safari/10600.6.3 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)","Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"]## 在user_agent列表中随机产生一个代理,作为模拟的浏览器user_agent = choice(user_agents)return user_agentdef get_page(list_url):"""获取包含特定关键字的留言链接"""user_agent = get_user_agent()headers = {'User-Agent': user_agent}# Make the request using the requests libraryresponse = requests.get(list_url, headers=headers)if response.status_code == 200:html_content = response.text# 使用 BeautifulSoup 解析 HTMLsoup = BeautifulSoup(html_content, 'html.parser')bump_elements = soup.find_all(class_='nump')# 提取数字并转换为整数nump_numbers = [int(element.text) for element in bump_elements]# 找出最大的数if nump_numbers:max_nump = max(nump_numbers)else:# 处理空序列的情况,例如给 max_nump 赋一个默认值max_nump = None  # 或者其他你认为合适的默认值return max_numpelse:print(f"Error: {response.status_code}")return Nonedef generate_urls(base_url, page_number, total_pages):urls = []for page in range(2, total_pages + 1, page_number):url = f"{base_url},f_{page}.html"urls.append(url)return urlsdef get_detail_urls_by_keyword(urls):comment, link, reads, date = [], [], [], []total_iterations = len(urls)# Create a tqdm instance for the progress barprogress_bar = tqdm(total=total_iterations, desc='Processing URLs', position=0, leave=True)# 在函数外定义一个锁lock = threading.Lock()def process_url(url):nonlocal comment, link, reads, date'''获取包含特定关键字的留言链接'''user_agent = get_user_agent()headers = {'User-Agent': user_agent}# Make the request using the requests libraryresponse = requests.get(url, headers=headers)encoding = chardet.detect(response.content)['encoding']# 解码响应内容if response.status_code == 200:html_content = response.content.decode(encoding)# 使用 BeautifulSoup 解析 HTMLsoup = BeautifulSoup(html_content, 'html.parser')#print(html_content)# Extract and convert relative URLs to absolute URLswith lock:links = []author_elements = soup.select('div.author a')for element in author_elements:href = element.get('href')if href:absolute_url = urljoin('https:', href)links.append(absolute_url)links = ['https://i.eastmoney.com/' + text.split('"//i.eastmoney.com/')[-1].split('">')[0] for text inlinks]link = [link[len('https://i.eastmoney.com/'):] if link.startswith('https://i.eastmoney.com/') else link forlink in links]# Extract commentscomment_elements = soup.select('div.reply')for element in comment_elements:message_id = element.text.strip().split(':')[-1]comment.append(message_id)# Extract datespattern = re.compile(r'\d{1,2}-\d{1,2} \d{2}:\d{2}')# Find all matches in the textdate = pattern.findall(html_content)# Extract readsread_elements = soup.select('div.read')for element in read_elements:message_id = element.text.strip().split(':')[-1]reads.append(message_id)# Update the progress barprogress_bar.update(1)else:print(f"Error: {response.status_code}")# Create threads for each URLthreads = []for url in urls:thread = threading.Thread(target=process_url, args=(url,))thread.start()threads.append(thread)# Wait for all threads to completefor thread in threads:thread.join()# Close the progress barprogress_bar.close()return comment, link, reads, datedef extract_and_combine(url):match = re.search(r'\d{6}', url)if match:extracted_number = match.group()result = extracted_numberreturn resultelse:return Nonedef process_dates(date_list):processed_dates = []current_year = 2023for date_str in date_list:try:# Adjust the format string based on the actual format of your datadate_obj = datetime.strptime(date_str, "%m-%d %H:%M")# Check if processed_dates is not empty before accessing its last elementif processed_dates and date_obj.month < processed_dates[-1].month:current_year -= 1# Replace the year in date_obj with the updated current_yearprocessed_date = date_obj.replace(year=current_year)processed_dates.append(processed_date)except ValueError as e:print(f"Error processing date '{date_str}': {e}")return processed_datesdef write_to_csv_file(comment, link, reads, date, result):"""将数据写入 CSV 文件Parameters:comment (list): 评论数列表link (list): 链接列表title (list): 标题列表reads (list): 阅读数列表date (list): 日期列表result (str): 结果标识Returns:None"""# 指定 CSV 文件的路径csv_file_path = result + "_评论.csv"# 将数据写入 CSV 文件with open(csv_file_path, 'w', newline='', encoding='utf-8') as csv_file:csv_writer = csv.writer(csv_file)# 写入表头csv_writer.writerow(['评论数', '链接', '阅读数', '日期'])# 写入数据csv_writer.writerows(zip(comment, link, reads, date))print(f"CSV 文件已生成: {csv_file_path}")def filter_and_append_links(comment, link):"""过滤评论数大于等于0的链接并添加到 final_link 列表中Parameters:comment (list): 包含评论数的列表link (list): 包含链接的列表Returns:final_link (list): 过滤后的链接列表"""final_link = []for i in range(4, len(link)):comment_value = int(comment[i])if comment_value >= 0:final_link.append(link[i])return final_linkdef remove_duplicates(input_list):unique_list = []for item in input_list:if item not in unique_list:unique_list.append(item)return unique_listdef process_result_links(links):# 调用去重函数result_link = remove_duplicates(links)# 使用循环和 remove 方法移除包含子列表的元素for item in result_link[:]:  # 使用切片创建副本,以防止在循环中修改原始列表if 'list' in item:result_link.remove(item)return result_linkdef get_information_for_url(url):influence, age, location, fan = [], [], [], []user_agent = get_user_agent()headers = {'User-Agent': user_agent}# Make the request using the requests libraryresponse = requests.get(url, headers=headers)if response.status_code == 200:html_content = response.text# 使用 BeautifulSoup 解析 HTMLprint(html_content)soup = BeautifulSoup(html_content, 'html.parser')# 提取影响力信息# Extract agesage_elements = soup.select('div.others_level p:contains("吧龄") span')for element in age_elements:age_text = element.text.strip()age.append(age_text)# Extract locationslocation_elements = soup.select('p.ip_info')for element in location_elements:text = element.text.strip()match = re.search(r':([^?]+)\?', text)if match:ip_location = match.group(1)location.append(ip_location)# Extract fansfan_elements = soup.select('div.others_fans a#tafansa span.num')for element in fan_elements:message_id = element.text.strip().split(':')[-1]fan.append(message_id)return influence, age, location, fanelse:print(f"Error: {response.status_code}")return Nonedef get_information(urls):influence, age, location, fan = [], [], [], []with concurrent.futures.ThreadPoolExecutor() as executor:results = list(tqdm(executor.map(get_information_for_url, urls), total=len(urls), desc="Processing URLs"))for result in results:influence.extend(result[0])age.extend(result[1])location.extend(result[2])fan.extend(result[3])return age, location, fandef write_to_csv(result_link, age, location, fan, result):# 构建 CSV 文件名csv_filename = result + "_用户.csv"# 将数据封装成字典列表data = [{"链接": link, "吧龄": a, "属地": loc, "粉丝": f}for link, a, loc, f in zip(result_link, age, location, fan)]# 使用 csv 模块创建 CSV 文件并写入数据,同时指定列名with open(csv_filename, 'w', newline='') as csvfile:fieldnames = ["链接", "吧龄", "属地", "粉丝"]writer = csv.DictWriter(csvfile, fieldnames=fieldnames)# 写入列名writer.writeheader()# 写入数据writer.writerows(data)print(f"Data has been written to {csv_filename}")def convert_to_guba_link(file_path):"""读取 Excel 文件中的六位数,将其转换为股吧链接Parameters:file_path (str): Excel 文件路径Returns:guba_links (list): 转换后的股吧链接列表"""guba_links = []try:# 读取 Excel 文件df = pd.read_excel(file_path)# 获取第一列的数据six_digit_numbers = df.iloc[:, 0]# 转换六位数为股吧链接for number in six_digit_numbers:# 使用 f-string 构建链接link = f"https://guba.eastmoney.com/list,{number:06d}.html"guba_links.append(link)except Exception as e:print(f"Error: {e}")return guba_linksdef main():"""主函数"""list_urls = convert_to_guba_link('number.xlsx')print('爬虫程序开始执行--->')i = 2for list_url in list_urls:page = 3print("总页数:",page)page_number = 1url_without_html = list_url.replace(".html", "")urls = generate_urls(url_without_html, page_number, page)print(urls)comment, link, reads, date = get_detail_urls_by_keyword(urls)print(comment)print(link)print(reads)print(date)date = process_dates(date)result = extract_and_combine(list_url)write_to_csv_file(comment, link, reads, date, result)link = process_result_links(link)age, location, fan = get_information(link)print(age)print(location)print(fan)write_to_csv(link, age, location, fan, result)print('抓取完个数:',i)i = i + 1if __name__ == '__main__':'''执行主函数'''main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/158450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小程序Tab栏与页面滚动联动

小程序tab栏切换与页面滚动联动 tab栏与页面滚动联动点击tab栏页面跳到指定位置滚动页面时切换tab栏 tab栏与页面滚动联动 在进行小程序开发时&#xff0c;需要实现点击tab栏页面滚动到某一指定位置&#xff0c;并且滚动页面时&#xff0c;小程序的tab栏进行切换。 在一开始&a…

黑苹果新手指导:名词解释常用软件常见问题说明

黑苹果新手指导&#xff1a;名词解释&常用软件&常见问题说明 写在前面名词解释系统篇引导篇工具篇 常见问题安装篇如何安装黑苹果&#xff1f;安装过程中卡在一排号怎么办&#xff1f;AMD处理器可以安装黑苹果 macOS吗&#xff1f;我的笔记本电脑为什么不能驱动独立显卡…

uni-app - 日期 · 时间选择器

目录 1.基本介绍 2.案例介绍 ①注意事项&#xff1a; ②效果展示 3.代码展示 ①view部分 ②js部分 ③css样式 1.基本介绍 从底部弹起的滚动选择器。支持五种选择器&#xff0c;通过mode来区分&#xff0c;分别是普通选择器&#xff0c;多列选择器&#xff0c;时间选择器&a…

虹科分享 | 平衡速度和优先级:为多样化的实时需求打造嵌入式网络(2)——实时通信系统的需求

现代实时应用的复杂性和需求不断增加&#xff0c;需要强大而可靠的通信系统。正如本系列第一部分所述&#xff0c;这些应用涵盖从秒到毫秒的广泛响应时间要求&#xff0c;它们的成功通常取决于其响应的精确时间。因此&#xff0c;所选的通信系统必须能够满足这些严格的时序限制…

API之 要求接口上传pdf 以 合同PDF的二进制数据,multpart方式上传

实现 //时间戳13位毫秒private function getMillisecond() {list($s1,$s2) explode( ,microtime());return (float)sprintf(%.0f,(floatval($s1) floatval($s2)) * 1000);}// 组装参数private function gysscPost1($url,$data){// $data[timestamp] 1694402111964;$data[tim…

自然语言处理常用方法和评价指标

常用方法 文本分类&#xff1a;如情感分析、主题标签分类。使用方法如朴素贝叶斯、支持向量机、神经网络等。信息提取&#xff1a;从文本中提取结构化信息&#xff0c;如命名实体识别&#xff08;NER&#xff09;、关系提取。语义分析&#xff1a;理解文本的含义&#xff0c;包…

怎么批量提取文件名字到Excel中?

怎么批量提取文件名字到Excel中&#xff1f;Excel是由微软公司开发的一种电子表格软件&#xff0c;它是Microsoft Office办公套件的一部分。Excel提供了强大的数据处理和分析功能&#xff0c;用户可以使用Excel创建、编辑和管理电子表格&#xff0c;进行各种计算、数据分析、图…

【C++ 学习 ㊴】- 详解 C++ 的 I/O 流

目录 一、C 的 I/O 流 二、C 的标准 I/O 流 三、C 的文件 I/O 流 一、C 的 I/O 流 C 语言有一套完成数据读写&#xff08;I/O&#xff09;的解决方案&#xff1a; 使用 scanf()、gets() 等函数从键盘读取数据&#xff0c;使用 printf()、puts() 等函数向屏幕输出数据&#…

909-2014-T2

文章目录 1.原题2.算法思想3.关键代码4.完整代码5.运行结果 1.原题 二叉树采用二叉链表存储结构&#xff0c;设计算法&#xff0c;判断二叉树是否为满二叉树。叙述算法思想并给出算法实现。 2.算法思想 通过一次遍历&#xff0c;得到结点个数和树的高度。用结点个数和树的高…

C/C++ 实现:自然排序:针对两个需要排序的字符串,不仅逐个比较每个字符的顺序,对于连在一起的数字字符会作为一个完整数字进行比较 某知名企业的笔试题

目录 题目描述: 分析: 代码实现: 完整代码: 运行结果: 题目描述: 下面是一个自然排序函数的声明,请实现该函数; 自然排序是指:针对两个需要排序的字符串,不仅逐个比较每个

linux驱动开发.之spi测试工具spidev_test源码(一)

同i2c-tools工具类似&#xff0c;spidev_test是用来测试SPI BUS的用户态程序&#xff0c;其源码存在kernel目录下的tools下&#xff0c;具体为tools\spi\spidev_test.c。buildroot同样也提供名为spidev_test的package&#xff0c;可以直接进行编译&#xff0c;方便用户调试spi总…

Maven optional的作用

Maven optional的作用 这里的optional作用&#xff0c;可参考How do optional dependencies work?。 Project-A -> Project-BThe diagram above says that Project-A depends on Project-B. When A declares B as an optional dependency in its POM, this relationship …

Python-对象与json互转-json读写-文件读写

文章目录 1.json2.类对象序列化3.调用exe进行数据交换4.总结 1.json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999…

全国市政公用事业和邮政、电信业发展数据,shp/excel格式

随着城市化进程的加速和人们对城市生活品质要求的提高&#xff0c;市政公用事业和邮政、电信业发展越来越受到关注。 今天我们来分享全国市政公用事业和邮政、电信业发展数据&#xff0c;为读者呈现一个更加全面的行业发展图景。 首先了解下数据的基本信息&#xff0c;格式为s…

2023亿发数字化智能工单,专业管理工单处理全流程,助力企业转型腾飞

伴随着智能化和信息化的不断深入&#xff0c;企业数字化转型势如腾飞。在这个过程中&#xff0c;工单管理成为生产、家电、后勤等多个管理场景下频繁应用的关键环节。如何满足管理方对设备、服务等智能化管理的需求&#xff0c;提升工单管理效率、规范管理流程&#xff0c;并实…

nginx:413 Request Entity Too Large

修改配置文件 nginx.conf&#xff0c;根据自己的实际情况修改大小 http {client_max_body_size 10m; }配置完成后重启nginx 参考文章 解决 413 Request Entity Too Large&#xff08;请求实体太大&#xff09;

Fiddler模拟弱网环境

1.设置弱网&#xff1a;Rules-》Customize Rules 上传速度&#xff1a;1KB/300ms1KB/0.3s3.33KB/s 下载速度&#xff1a;1KB/150ms1KB/0.15s6.67KB/s 2.启动弱网&#xff1a;Rules-》Performance-》Simulate Modem Speeds 开启后&#xff0c;此项为勾选状态 3.验证弱网生效…

光量子计算再创融资高峰!法国 Quandela获投5000万欧元

​&#xff08;图片来源&#xff1a;网络&#xff09; 法国光量子计算公司Quandela致力于开发首台光量子计算机&#xff0c;目前已获得超过5,000万欧元的巨额融资。投资者包括通过“法国2030计划”获得的法国政府支持以及银行合作伙伴、个人。新的投资者包括法国投资公司Seren…

第十九章 绘图

目录 Java绘图类 Graphics 类 Graphics2D类 绘制图形 绘图颜色与画笔属性 设置颜色 设置画笔 绘制文本 设置字体 显示文字 显示图片 图像处理 放大与缩小 图像翻转 图像旋转 图像倾斜 Java绘图类 Graphics 类 Grapics 类是所有图形上…