当前位置: 首页 > news >正文

Beaustiful Soup爬虫案例

文章目录

  • 1 第三方库
  • 2 爬取
    • 2.1 初始化函数
    • 2.2 结束时关闭数据库
    • 2.3 生成header
    • 2.4 获取请求body
    • 2.5 解析异步json数据
    • 2.6 使用BS4的find方法解析
    • 2.7 写入口函数
    • 2.8 调用
  • 3 完整代码

1 第三方库

  • 获取随机UA
pip install fake-useragent
  • 连接数据库
$ pip3 install PyMySQL
  • 发起请求
pip install requests
  • 解析页面
pip install beautifulsoup4
  • 进度条
pip install tqdm

2 爬取

2.1 初始化函数

  • 新建爬虫类
class mySpider:
  • 创建数据库连接和初始化url
# 初始化urldef __init__(self, url):self.url = url# 计数,请求一个页面的次数,初始值为1self.count = 1# 数据库连接对象self.db = pymysql.connect(host='localhost',port=3306,user='root',password='123456',database='test')# 创建游标对象self.cursor = self.db.cursor()

2.2 结束时关闭数据库

  • 关闭数据库释放资源,方法运行完后调用。
# 结束断开数据库连接def __del__(self):self.cursor.close()self.db.close()print("关闭数据库!")

2.3 生成header

  • 使用第三方库fake-useragent生成随机UA
# 获取一个headerdef getHeader(self):# 实例化ua对象ua = UserAgent()# 随机获取一个uaheaders = {'User-Agent': ua.random}return headers

2.4 获取请求body

  • 注意有返回值的递归,要把返回值返回,回调时加return
def getBody(self, url, send_type, data):# 每次请求都随机停顿一些时间# time.sleep(random.randint(1, 2))# 在超时时间内,对于失败页面尝试请求三次if self.count <= 3:try:if send_type == 'get':res = requests.get(url=url, headers=self.getHeader(), params=data, timeout=2)elif send_type == 'post':res = requests.post(url=url, headers=self.getHeader(), data=data, timeout=2)else:print("未输入send_type,直接返回None")res = Nonereturn resexcept Exception as e:print(e)self.count += 1print(f"第{self.count}次,发起请求")# 再次调用自己,并把值返回,(注意要加return)return self.getBody(url, send_type, data)

2.5 解析异步json数据

  • 解析异步json数据
def parseData(self, dataList):# 循环查看详情for row in tqdm(dataList, desc='爬取进度'):# 请求详情页urlurlDetail = f"https://www.baidu.com/CTMDS/pub/PUB010100.do?method=handle04&compId={row['companyId']}"# 发起请求# 每次请求都初始化一次self.countself.count = 1res = self.getBody(url=urlDetail, send_type='get', data={})if res is not None:# 解析htmlself.parseHtml(row=row, htmlText=res.text)else:print(f"{urlDetail}请求失败!")

2.6 使用BS4的find方法解析

  • find_all() 方法用来搜索当前 tag 的所有子节点,并判断这些节点是否符合过滤条件,最后以列表形式将符合条件的内容返回,语法格式如下
    find_all( name , attrs , recursive , text , limit )
  • 参数说明
  • name:查找所有名字为 name 的 tag 标签,字符串对象会被自动忽略。
  • attrs:按照属性名和属性值搜索 tag 标签,注意由于 class 是 Python 的关键字吗,所以要使用 “class_”。
  • recursive:find_all() 会搜索 tag 的所有子孙节点,设置 recursive=False 可以只搜索 tag 的直接子节点。
  • text:用来搜文档中的字符串内容,该参数可以接受字符串 、正则表达式 、列表、True。
  • limit:由于 find_all() 会返回所有的搜索结果,这样会影响执行效率,通过 limit 参数可以限制返回结果的数量。
def parseHtml(self, row, htmlText):soup = BeautifulSoup(htmlText, 'html.parser')# 获取备案信息divList = soup.find_all('div', class_=['col-md-8'])divtextList = [re.sub(r'\s+', '', div.text) for div in divList]# 获取其他机构地址divListOther = soup.find_all('div', class_=['col-sm-8'])divtextListOther = [re.sub(r'\s+', '', div.text) for div in divListOther]otherOrgAdd = ','.join(divtextListOther)# 插入数据库companyId = row['companyId']linkTel = row['linkTel']recordNo = row['recordNo']areaName = row['areaName']linkMan = row['linkMan']address = row['address']compName = row['compName']recordStatus = row['recordStatus']cancelRecordTime = row.get('cancelRecordTime', '')compLevel = divtextList[2]recordTime = divtextList[6]sql1 = "insert INTO medical_register(company_id,area_name,record_no,comp_name,address,link_man,link_tel,record_status,comp_level,record_time,cancel_record_time,other_org_add) "sql2 = f"values('{companyId}','{areaName}','{recordNo}','{compName}','{address}','{linkMan}','{linkTel}','{recordStatus}','{compLevel}','{recordTime}','{cancelRecordTime}','{otherOrgAdd}')"sql3 = sql1 + sql2# 执行sqlself.cursor.execute(sql3)# 提交self.db.commit()# 获取备案专业和主要研究者信息tbody = soup.find('tbody')trList = tbody.find_all('tr')# 对tr循环获取tdfor tr in trList:tdList = tr.find_all('td')tdTextList = [td.text for td in tdList]tdTextList.insert(0, companyId)# print(tdTextList)# 插入数据库sql4 = "insert into medical_register_sub (company_id,professional_name,principal_investigator,job_title) values(%s,%s,%s,%s)"self.cursor.execute(sql4, tdTextList)# 提交到数据库self.db.commit()

2.7 写入口函数

  • 这里pageSize直接干到最大,懂的都懂!
def run(self):try:# 拿第一页的数据data = {'pageSize': 1350, 'curPage': 1}# 每次请求都初始化一次self.countself.count = 1res = self.getBody(url=self.url, send_type='post', data=data)if res is not None:# 加载为jsonjsonRes = json.loads(res.text)# 查看响应状态码status = jsonRes['success']# 如果状态为Trueif status == True:# 获取数据dataList = jsonRes['data']# 处理数据self.parseData(dataList=dataList)else:print(f"{self.url}请求失败")except Exception as e:print('发生错误!', e)

2.8 调用

  • 调用
if __name__ == '__main__':spider = mySpider('https://www.baidu.com/CTMDS/pub/PUB010100.do?method=handle05')spider.run()

3 完整代码

  • 完整代码
import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import time
import random
import json
import re
import pymysql
from tqdm import tqdmclass mySpider:# 初始化urldef __init__(self, url):self.url = url# 计数,请求一个页面的次数,初始值为1self.count = 1# 数据库连接对象self.db = pymysql.connect(host='localhost',port=3306,user='root',password='logicfeng',database='test2')# 创建游标对象self.cursor = self.db.cursor()# 结束断开数据库连接def __del__(self):self.cursor.close()self.db.close()print("关闭数据库!")# 获取一个headerdef getHeader(self):# 实例化ua对象ua = UserAgent()# 随机获取一个uaheaders = {'User-Agent': ua.random}return headers# 获取请求bodydef getBody(self, url, send_type, data):# 每次请求都随机停顿一些时间# time.sleep(random.randint(1, 2))# 在超时时间内,对于失败页面尝试请求三次if self.count <= 3:try:if send_type == 'get':res = requests.get(url=url, headers=self.getHeader(), params=data, timeout=2)elif send_type == 'post':res = requests.post(url=url, headers=self.getHeader(), data=data, timeout=2)else:print("未输入send_type,直接返回None")res = Nonereturn resexcept Exception as e:print(e)self.count += 1print(f"第{self.count}次,发起请求")# 再次调用自己,并把值返回,(注意要加return)return self.getBody(url, send_type, data)# 解析bodydef parseData(self, dataList):# 循环查看详情for row in tqdm(dataList, desc='爬取进度'):# 请求详情页urlurlDetail = f"https://www.baidu.com/CTMDS/pub/PUB010100.do?method=handle04&compId={row['companyId']}"# 发起请求# 每次请求都初始化一次self.countself.count = 1res = self.getBody(url=urlDetail, send_type='get', data={})if res is not None:# 解析htmlself.parseHtml(row=row, htmlText=res.text)else:print(f"{urlDetail}请求失败!")# 解析页面def parseHtml(self, row, htmlText):soup = BeautifulSoup(htmlText, 'html.parser')# 获取备案信息divList = soup.find_all('div', class_=['col-md-8'])divtextList = [re.sub(r'\s+', '', div.text) for div in divList]# 获取其他机构地址divListOther = soup.find_all('div', class_=['col-sm-8'])divtextListOther = [re.sub(r'\s+', '', div.text) for div in divListOther]otherOrgAdd = ','.join(divtextListOther)# 插入数据库companyId = row['companyId']linkTel = row['linkTel']recordNo = row['recordNo']areaName = row['areaName']linkMan = row['linkMan']address = row['address']compName = row['compName']recordStatus = row['recordStatus']cancelRecordTime = row.get('cancelRecordTime', '')compLevel = divtextList[2]recordTime = divtextList[6]sql1 = "insert INTO medical_register(company_id,area_name,record_no,comp_name,address,link_man,link_tel,record_status,comp_level,record_time,cancel_record_time,other_org_add) "sql2 = f"values('{companyId}','{areaName}','{recordNo}','{compName}','{address}','{linkMan}','{linkTel}','{recordStatus}','{compLevel}','{recordTime}','{cancelRecordTime}','{otherOrgAdd}')"sql3 = sql1 + sql2# 执行sqlself.cursor.execute(sql3)# 提交self.db.commit()# 获取备案专业和主要研究者信息tbody = soup.find('tbody')trList = tbody.find_all('tr')# 对tr循环获取tdfor tr in trList:tdList = tr.find_all('td')tdTextList = [td.text for td in tdList]tdTextList.insert(0, companyId)# print(tdTextList)# 插入数据库sql4 = "insert into medical_register_sub (company_id,professional_name,principal_investigator,job_title) values(%s,%s,%s,%s)"self.cursor.execute(sql4, tdTextList)# 提交到数据库self.db.commit()# 入口函数def run(self):try:# 拿第一页的数据data = {'pageSize': 1350, 'curPage': 1}# 每次请求都初始化一次self.countself.count = 1res = self.getBody(url=self.url, send_type='post', data=data)if res is not None:# 加载为jsonjsonRes = json.loads(res.text)# 查看响应状态码status = jsonRes['success']# 如果状态为Trueif status == True:# 获取数据dataList = jsonRes['data']# 处理数据self.parseData(dataList=dataList)else:print(f"{self.url}请求失败")except Exception as e:print('发生错误!', e)if __name__ == '__main__':spider = mySpider('https://www.百度.com/CTMDS/pub/PUB010100.do?method=handle05')spider.run()

相关文章:

Beaustiful Soup爬虫案例

文章目录 1 第三方库2 爬取2.1 初始化函数2.2 结束时关闭数据库2.3 生成header2.4 获取请求body2.5 解析异步json数据2.6 使用BS4的find方法解析2.7 写入口函数2.8 调用 3 完整代码 1 第三方库 获取随机UA pip install fake-useragent连接数据库 $ pip3 install PyMySQL发起…...

【Redis】Redis与SSM整合Redis注解式缓存Redis解决缓存问题

一&#xff0c;Redis与ssm整合 1.1 pom.xml配置 在pom.xml中配置相关的redis文件 redis文件&#xff1a; <redis.version>2.9.0</redis.version> <redis.spring.version>1.7.1.RELEASE</redis.spring.version><dependency><groupId>red…...

谈一谈SQLite、MySQL、PostgreSQL三大数据库

每一份付出&#xff0c;必将有一份收货&#xff0c;就像这个小小的果实&#xff0c;时间到了&#xff0c;也就会开花结果… 三大数据库概述 SQLite、MySQL 和 PostgreSQL 都是流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;但它们在功能、适用场景和性…...

【微软技术栈】C#.NET 中的本地化

本文内容 资源文件注册本地化服务使用 IStringLocalizer<T> 和 IStringLocalizerFactory将其放在一起 本地化是针对应用支持的每个区域性&#xff0c;将应用资源转换为本地化版本的过程。 只有在完成本地化评审步骤&#xff0c;以验证全球化应用是否做好本地化准备后&a…...

【qemu逃逸】华为云2021-qemu_zzz

前言 虚拟机用户名&#xff1a;root 无密码 设备逆向 经过逆向分析&#xff0c;可得实例结构体大致结构如下&#xff1a; 其中 self 指向的是结构体本身&#xff0c;cpu_physical_memory_rw 就是这个函数的函数指针。arr 应该是 PCI 设备类结构体没啥用&#xff0c;就直接用…...

vue递归获取树形菜单

文章目录 前言什么是递归&#xff1f; 一、数据集二、 递归函数三、打印树形结构展示 前言 什么是递归&#xff1f; 程序调用自身的编程技巧称为递归&#xff08; recursion&#xff09;。 递归 粗略的理解为 循环 &#xff0c;只不过 递归 是调用自身。 在实际使用中&#xf…...

[ubuntu]ubuntu22.04默认源和国内源

sudo vi /etc/apt/sources.list 请选择和系统对应的版本&#xff0c;查看系统版本命令&#xff1a; lsb_release -a Distributor ID: Ubuntu Description: Ubuntu 22.04 LTS Release: 22.04 Codename: jammy Ubuntu不同的版本配置的有…...

Map和ForEach的区别,For in和For of的区别

Map和ForEach的区别&#xff1a; 共同点&#xff1a;都可以遍历数组&#xff0c;this指向window&#xff0c;都不会改变原数组。 不同点&#xff1a;map返回一个数组&#xff0c;不会对空数组进行检测&#xff0c;如果是空数组map的话还是返回一个空数组&#xff0c;而空数组…...

json字符串属性名与实体类字段名转换

在项目开发过程中&#xff0c;会遇到实体类字段名与交互的json对象属性名不一致的情况&#xff0c;比如前段使用的是下划线方式定义&#xff0c;后端采用的是驼峰式定义&#xff0c;其他系统使用t表示一个时间戳&#xff0c;自己的系统使用timestamp定义。遇到这种情况&#xf…...

Vue Vuex模块化编码

正常写vuex的index的时候如果数据太多很麻烦&#xff0c;如有的模块是管理用户信息或修改课程等这两个是不同一个种类的&#xff0c;如果代码太多会造成混乱&#xff0c;这时候可以使用模块化管理 原始写法 如果功能模块太多很乱 import Vue from vue import Vuex from vuex …...

消费者忠诚度研究:群狼调研帮您制定忠诚客户计划

在当今竞争激烈的市场环境中&#xff0c;消费者忠诚度对于企业的成功至关重要。消费者忠诚度不仅关系到企业的市场份额和盈利能力&#xff0c;还直接影响着企业的品牌形象和声誉。群狼调研作为一家专业的市场研究机构&#xff0c;专注于消费者忠诚度研究&#xff0c;为企业提供…...

接口幂等性详解

1. 什么是幂等性 幂等性指的是对同一个操作的多次执行所产生的影响与一次执行的影响相同。无论操作执行多少次&#xff0c;系统状态都应该保持一致。 在计算机科学和网络领域中&#xff0c;幂等性通常用来描述服务或操作的特性。对于RESTful API或HTTP方法&#xff0c;一个幂…...

Java操作redis常见类型数据存储

一&#xff0c;Java连接Redis 1.1 导入依赖 打开IDEA在pom.xml导入依赖 注意&#xff1a;要在dependencies标签中导入 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version> &…...

【深度学习】pytorch——Autograd

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 深度学习专栏链接&#xff1a; http://t.csdnimg.cn/dscW7 pytorch——Autograd Autograd简介requires_grad计算图没有梯度追踪的张量ensor.data 、tensor.detach()非叶子节点的梯度计算图特点总结 利用Autograd实…...

【ARM 安全系列介绍 1 -- 奇偶校验与海明码校验详细介绍】

文章目录 奇偶校验介绍奇偶校验 python 实现奇偶校验C代码实现 海明码详细介绍 奇偶校验介绍 奇偶校验是一种错误检测方法&#xff0c;广泛应用于计算机内部以及数据通信领域。其基本原理是为了使得一组数据&#xff08;通常是一字节8位&#xff09;中的“1”的个数为偶数或奇…...

分享34个发布商会PPT,总有一款适合您

分享34个发布商会PPT&#xff0c;总有一款适合您 链接&#xff1a;https://pan.baidu.com/s/1jP9toqTZONWeDIcxvw1wxg?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知识付费甚…...

047_第三代软件开发-日志分离

第三代软件开发-日志分离 文章目录 第三代软件开发-日志分离项目介绍日志分离用法 关键字&#xff1a; Qt、 Qml、 log、 日志、 分离 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object Language&#xff09;和 C 的强…...

ChinaSoft 论坛巡礼 | 系统与网络安全论坛

2023年CCF中国软件大会&#xff08;CCF ChinaSoft 2023&#xff09;由CCF主办&#xff0c;CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办&#xff0c;将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…...

Ubuntu Gitlab安javascript:void(‘numberedlist‘)装

原因&#xff1a; 代码越改越多&#xff0c;越难维护&#xff0c;开发代码和发布代码融为一体&#xff1b;2人以上开发&#xff0c;都会修改代码&#xff0c;修改次数一多&#xff0c;代码难以维护 其中&#xff1a;前往Gitlab官网&#xff1a;gitlab/gitlab-ce - Packages pa…...

11.4-GPT4AllTools版本已开始对小部分GPT3.5用户内测推送

OpenAI已经开始小规模推送GPT4 AllTools功能&#xff0c;部分GPT博主已经第一时间体验了此功能&#xff0c;此功能特色是整合目前的多模态功能以及文件上传和联网模块&#xff0c;无需切换&#xff0c;更要全面综合 可上传包括 PDF、数据文件在内的任意文档&#xff0c;并进行分…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...