赞
踩
BeautifulSoup是一个可以从HTML或XML文件中提取数据的Python库.
官方文档: https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html
Python2.7.3之前的版本和Python3中3.2.2之前的版本, 必须安装lxml或html5lib,
因为那些Python版本的标准库中内置的HTML解析方法不够稳定.
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
Python标准库 | BeautifulSoup(markup, “html.parser”) | Python的内置标准库执行速度适中文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml HTML 解析器 | BeautifulSoup(markup, “lxml”) | 速度快文档容错能力强 | 需要安装C语言库 |
lxml XML 解析器 | BeautifulSoup(markup, [“lxml”, “xml”])``BeautifulSoup(markup, “xml”) | 速度快唯一支持XML的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup, “html5lib”) | 最好的容错性以浏览器的方式解析文档生成HTML5格式的文档 | 速度慢不依赖外部 |
安装BeautifulSoup4与解析器:
pip install BeautifulSoup4
pip install lxml
pip install html5lib
生成节点 Tag对象:
from bs4 import BeautifulSoup
soup = BeautifulSoup(需要解析的字符串, 使用的解析器)
文档的容错能力: 指的是在html代码不完整的情况下, 使用该模块可以识别该错误。
使用BeautifulSoup解析上述代码, 能够得到一个 BeautifulSoup 的对象, 并能按照标准的缩进格式的结构输出.
from bs4 import BeautifulSoup # html字符串 html_doc = """ <html><head><title>页面标题</title></head> <body> <p class="title"><b>标题</b></p> <p class="story">开始, <a href="https://www.baidu.com" class="sister" id="link1">A</a> <a href="https://www.baidu.come" class="sister" id="link2">B</a> 中间 <a href="https://www.baidu.com" class="sister" id="link3">C</a> 结束.</p> <p class="story">...</p> """ soup = BeautifulSoup(html_doc, 'lxml') # 具有容错功能 res = soup.prettify() # 处理好缩进, 结构化显示 print(res)
遍历文档树: 即直接通过标签名字选择, 特点是选择速度快, 但如果存在多个相同的标签则只返回第一个.
* 多个相同标签只返回第一个, 第一个算遍历, 其他的都不算!
soup = BeautifulSoup(html_doc, 'lxml')
# 与.find()方法速度一致
print(soup.p) # <p class="title"><b>标题</b></p>
# 值是提供Tag对象
# 推荐方法(速度快)
print(soup.body.p) # <p class="title"><b>标题</b></p>
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p.name) # p
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p.attrs) # {'class': ['title']} 值是一个列表
print(soup.body.p.attrs['class']) # ['title']
print(soup.body.p['class']) # ['title']
* 1. 文本内容
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p.text) # 标题
print(soup.body.p.get_text())
soup = BeautifulSoup(html_doc, 'lxml')
# 获取第二个p标签, next_sibling下一个兄弟标签, 空行算一个next_sibling
print(soup.body.p.next_sibling.next_sibling.text)
"""
开始,
A
B 中间
C
结束.
"""
如果tag包含了多个子节点, tag就无法确定
.string 方法应该调用哪个子节点的内容, .string 的输出结果是 None.
如果只有一个子节点那么就输出该子节点的文本,比如下面的这种结构, .string 返回为None,
但.strings就可以找到所有文本, 值是一个生成器.
soup = BeautifulSoup(html_doc, 'lxml')
# 第一个p标签
print(soup.body.p.string)
# 第二个p标签, 标签下文本只有一个, 没有其他标签时, 可以取到值, 否则为None
print(soup.body.p.next_sibling.next_sibling.string)
# 第一个p标签
print(soup.body.p.strings) # <generator object Tag._all_strings at 0x0000017A63065740>
print(list(soup.body.p.strings)) # ['标题']
# 第二个p标签
print(list(soup.body.p.next_sibling.next_sibling.strings)) # ['开始,\n', 'A', '\n', 'B', ' 中 间\n', 'C', '\n结束.']
soup = BeautifulSoup(html_doc, 'lxml')
for line in soup.body.p.next_sibling.next_sibling.stripped_strings: # 去掉空白
print(line)
"""
开始,
A
B
中 间
C
结束.
"""
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.head.title.text)
print(soup.body.a.text)
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p.contents) # p下所有子节点
print(soup.body.p.children) # 得到一个迭代器,包含p下所有子节点
for i, child in enumerate(soup.p.children):
print(i, child)
print(soup.p.descendants) # 获取子孙节点, p下所有的标签都会选择出来
for i, child in enumerate(soup.p.descendants):
print(i, child)
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.a.parent) # 获取a标签的父节点
print(soup.a.parents) # 找到a标签所有的祖先节点,父亲的父亲,父亲的父亲的父亲...
for a in soup.a.parents:
print(a, '\n') # 会有两个html标签
* 空行被算成一个兄弟.
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.a.next_sibling) # 下一个兄弟
print(soup.body.a.previous_sibling) # 上一个兄弟
print(list(soup.body.a.next_siblings)) # 下面的兄弟们=>生成器对象
print(soup.body.a.previous_siblings) # 上面的兄弟们=>生成器对象
五种过滤器: 字符串, 正则表达式, 列表, True/False, 函数方法
* 1. 字符串过滤()
find(): 找到一个就放回
find_all(): 找多个
...
soup = BeautifulSoup(html_doc, 'lxml') print(soup.find('p')) # 标签查找 print(soup.find(name='p')) # 结果是一个Tag对象 print(soup.find(class_='title')) # 类查找 print(soup.find(attrs={'class': 'title'})) print(soup.find(id="link1")) # id查找 print(soup.find(attrs={'id': 'link1'})) print(soup.find(href="https://www.baidu.com")) # 属性查找 # 条件可以有多个 为 and关系 print(soup.find(id="link1", class_='sister')) print(soup.find_all(name='p')) # 结果是一个列表, 存放Tag对象
* 2. 正则表达式
import re
soup = BeautifulSoup(html_doc, 'lxml')
re_t = re.compile('^t')
print(soup.find(class_=re_t)) # <p class="title"><b>标题</b></p>
* 3. 列表
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.find_all(class_=['title', 'sister']))
* 4. True/False
soup = BeautifulSoup(html_doc, 'lxml')
# 存在或不存在否个属性
print(soup.find(id=True))
print(soup.p.find(id=False))
print(soup.find(href=True))
* 5. 自定义函数
soup = BeautifulSoup(html_doc, 'lxml')
# 定义函数
def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')
print(soup.body.find_all(has_class_but_no_id))
* 6. limit 参数与 recursive参数
limit: 限制条数
recursive: 当前层级查询不到, 递归查询(默认开启)
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.find_all(name='p', limit=1))
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.find_all(name='b', recursive=False))
select 返回的是列表形式.
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.select('#link1'))
print(soup.select('body>p>b'))
print(soup.select('body p b'))
* 1. 修改标签名称
soup = BeautifulSoup(html_doc, 'lxml')
soup.body.p.name = 'h3'
print(soup.body.h3.name) # 将第一个p标签改为h3标签, html中没有h3会报错
* 2. 修改属性值
soup = BeautifulSoup(html_doc, 'lxml')
soup.body.p['class'] = 'c1'
print(soup.body.p.attrs) # {'class': 'c1'}
* 3. 修改值
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p.string) # 标题
soup.body.p.string = 'xxx'
print(soup.body.p.string) # xxx
* 4. 添加值
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p.string) # 标题
soup.body.p.string = 'xxx'
soup.body.p.append('abcd') # 添加值
print(soup.body.p.string) # None
print(soup.body.p.text) # xxxabcd
* 5. 删除标签
soup = BeautifulSoup(html_doc, 'lxml')
print(soup.body.p) # 展示第一个标签
soup.body.p.decompose() # 删除第一个p标签
print(soup.body.p) # 展示原第二标签
宝塔: 宝塔面板是一款支持windows和linux系统的服务器管理软件, 可通过Web端管理服务器, 提升运维效率.
使用宝塔前: 手工输入命令安装各类软件, 操作起来费时费力并且容易出错.
而且需要记住很多Linux的命令,非常复杂.
使用宝塔后: 2分钟装好面板, 一键管理服务器, 鼠标点几下就能替代以前的复杂繁多命令,
操作简单, 看一眼就会使用. (图形化替代命令行操作)
JumpServer跳板机/堡垒机: 是一类可作为跳板批量操作远程设备的网络设备,
提供了认证、授权、审计和自动化运维等功能...
jumpserver组件说明
jumpserver堡垒机由以下三个部分组成:
* 1.jumpserver
jumpserver是jumpserver的核心组件, 是一个使用Python的django开发的管理后台, 支持restful API.
* 2.coco
coco是SSH Server和Web Terminal Server的组件,提供SSH和WebSocket接口, 使用paramiko和flask开发.
* 3.luna
luna是Web Terminal Server的前端, 前端页面均由该项目提供, 主要负责页面后台的渲染.
网站: https://www.autohome.com.cn/news/2/#liststart
需要获取: 标题, 图片, 简介, 链接
使用BeautifulSoup,从HTML文件中提取数据.
* 1. 分析网站
import requests
res = requests.get('https://www.autohome.com.cn/news/1/#liststart')
print(res.text)
得到的ul信息中有文章也有广告.
有h3标签的是文字, 没有h3标签的广告获取是空li标签.
广告
空标签
文章链接与封面路由
* 2. 使用BeautifulSoup获取html的ul数据.
import requests
from bs4 import BeautifulSoup
# 获取相应对象
res = requests.get('https://www.autohome.com.cn/news/1/#liststart')
# 生成文档对象 (html文件, 解析器)
soup = BeautifulSoup(res.text, 'html.parser')
# 查找ul的数据 查找class为article的标签数据, class是关键字, 加后缀_使用class_
# 得到一个Tag标签对象
ul = soup.find(class_='article')
print(ul)
* 3. 查询ul标签下所有的li标签
import requests
from bs4 import BeautifulSoup
# 获取相应对象
res = requests.get('https://www.autohome.com.cn/news/1/#liststart')
# 生成文档对象 (html文件, 解析器)
soup = BeautifulSoup(res.text, 'html.parser')
# 查找ul的数据 查找class为article的标签数据, class是关键字, 加后缀_使用class_
ul = soup.find(class_='article')
# 查找ul下的所有li标签, 得到一个列表
li_list = ul.find_all(name='li')
print(li_list)
* 4. 获取标题, 图片, 简介, 链接的信息.
import requests from bs4 import BeautifulSoup # 获取相应对象 res = requests.get('https://www.autohome.com.cn/news/1/#liststart') # 生成文档对象 (html文件, 解析器) soup = BeautifulSoup(res.text, 'html.parser') # 查找ul的数据 查找class为article的标签数据, class是关键字, 加后缀_使用class_ ul = soup.find(class_='article') # 查找ul下的所有li标签, 得到一个列表 li_list = ul.find_all(name='li') for li in li_list: # 剔除非文章的li标签, 获取不到h3的都不是文字 title = li.find(name='h3') # 得到h3标签对象 if title: # 获取标题 title = title.text # 获取文章链接(链接缺少https:) article_url = 'https:' + li.find('a').attrs.get('href') # 获取封面, 查找img标签, .attrs获取标签的所有的属性, 值是一个字典. 通过get获取到值 img_url = li.find(name='img').attrs.get('src') # 判断封面链接字符串是否是https开头(有一部分是, 有一部分不是) img_url = img_url if img_url.startswith('https:') else 'https:' + img_url # 获取文章简介 desc = li.find('p').text print( f""" 标题: {title}, 文章链接: {article_url}, 封面: {img_url}, 简介: {desc} """ )
* 1. 分析免费代理网站
地址: http://www.66ip.cn/1.html
import requests
url = 'http://www.66ip.cn/1.html'
res = requests.get(url)
res.encoding = res.apparent_encoding
print(res.text)
* 2. 获取ip表单
import requests
from bs4 import BeautifulSoup
url = 'http://www.66ip.cn/1.html'
res = requests.get(url)
res.encoding = res.apparent_encoding
soup = BeautifulSoup(res.text, 'lxml')
# 获取表单的节点(页面中有多个表单标签, 需要的ip表单在最后一个)
print(soup.find_all(name='table')[-1])
<table width='100%' border="2px" cellspacing="0px" bordercolor="#6699ff"> <tr> <td>ip</td> <td>端口号</td> <td>代理位置</td> <td>代理类型</td> <td>验证时间</td> </tr> <tr> <td>165.225.20.14</td> <td>10605</td> <td>宁夏回族自治区中卫市</td> <td>高匿代理</td> <td>2022年06月17日06时 验证</td> </tr> <tr> <td>8.215.27.71</td> <td>3128</td> <td>吉林省辽源市</td> <td>高匿代理</td> <td>2022年06月17日04时 验证</td> </tr> <tr> <td>103.155.54.245</td> <td>84</td> <td>广西壮族自治区桂林市</td> <td>高匿代理</td> <td>2022年06月17日02时 验证</td> </tr> <tr> <td>183.245.6.120</td> <td>8080</td> <td>云南省保山市</td> <td>高匿代理</td> <td>2022年06月17日00时 验证</td> </tr> </table>
* 3. 获取表单中tr的标签信息
import requests from bs4 import BeautifulSoup url = 'http://www.66ip.cn/1.html' res = requests.get(url) res.encoding = res.apparent_encoding soup = BeautifulSoup(res.text, 'lxml') # 获取表单的节点(页面中有多个表单标签, 需要的ip表单在最后一个) table = soup.find_all(name='table')[-1] # 获取表单中的子节点, 遍历tr标签 for tr in table.children: print(tr)
* table.children 获取table下说有的子标签, 行号算一个标签!!!
正常的标签: <!--<class 'bs4.element.Tag'>-->
空的标签: <!--<class 'bs4.element.NavigableString'>-->
<!--<class 'bs4.element.NavigableString'>--> <tr> <td>ip</td> <td>端口号</td> <td>代理位置</td> <td>代理类型</td> <td>验证时间</td> </tr> <!--<class 'bs4.element.Tag'>--> <!--<class 'bs4.element.NavigableString'>--> <tr> <td>165.225.20.14</td> <td>10605</td> <td>宁夏回族自治区中卫市</td> <td>高匿代理</td> <td>2022年06月17日06时 验证</td> </tr> <!--<class 'bs4.element.Tag'>--> <tr> <td>8.215.27.71</td> <td>3128</td> <td>吉林省辽源市</td> <td>高匿代理</td> <td>2022年06月17日04时 验证</td> </tr> <!--<class 'bs4.element.Tag'>--> <tr> <td>103.155.54.245</td> <td>84</td> <td>广西壮族自治区桂林市</td> <td>高匿代理</td> <td>2022年06月17日02时 验证</td> </tr> <!--<class 'bs4.element.Tag'>--> <tr> <td>183.245.6.120</td> <td>8080</td> <td>云南省保山市</td> <td>高匿代理</td> <td>2022年06月17日00时 验证</td> </tr> <!--<class 'bs4.element.Tag'>--> <!--<class 'bs4.element.NavigableString'>-->
* 4. 获取表单中tr的标签信息(剔除空行标签)
import requests import bs4 from bs4 import BeautifulSoup url = 'http://www.66ip.cn/1.html' res = requests.get(url) res.encoding = res.apparent_encoding soup = BeautifulSoup(res.text, 'lxml') # 获取表单的节点(页面中有多个表单标签, 需要的ip表单在最后一个) table = soup.find_all(name='table')[-1] # 获取表单中的子节点, 遍历tr标签 for tr in table.children: if isinstance(tr, bs4.element.Tag): print(tr)
* 5. 获取表单中的td标签
...
# 获取表单中的子节点, 遍历tr标签
for tr in table.children:
if isinstance(tr, bs4.element.Tag):
# 遍历tr下的td标签
for td in tr.children:
print(td)
print('----')
<td>ip</td>
<td>端口号</td>
<td>代理位置</td>
<td>代理类型</td>
<td>验证时间</td>
----
<td>165.225.20.14</td>
<td>10605</td>
<td>宁夏回族自治区中卫市</td>
<td>高匿代理</td>
<td>2022年06月17日06时 验证</td>
* 6. 正则匹配获取ip与端口
import requests import bs4 from bs4 import BeautifulSoup import re url = 'http://www.66ip.cn/1.html' res = requests.get(url) res.encoding = res.apparent_encoding soup = BeautifulSoup(res.text, 'lxml') # 获取表单的节点(页面中有多个表单标签, 需要的ip表单在最后一个) table = soup.find_all(name='table')[-1] # 获取表单中的子节点, 遍历tr标签 # 定义一个列表(链接池) ip_port_list = [] for tr in table.children: if isinstance(tr, bs4.element.Tag): # tr.text会展示所有td的内容 # ip正则 re_ip = re.compile(r'^\d+.\d+.\d+.\d+$') ip = tr.find(text=re_ip) # 匹配成功拿到值, 匹配不成功为None # port正则 re_port = re.compile(r'^\d+$') port = tr.find(text=re_port) # 将ip与port放到列表中 if ip and port: # 协议类型 http_type_list = ['http', 'https'] # 代理ip端口 ip_port = ip + ":" + port for http_type in http_type_list: try: # 测试是否可以正常使用成功在将ip与port存到链接值中(使用代理失败会报错) res = requests.get('https://www.baidu.com/', proxies={http_type: ip_port}, timeout=10) if res.status_code == 200: ip_port_list.append((http_type, ip_port)) print('ok') # 网页中没有提示代理是http还是https except Exception as e: pass print(ip_port_list) """ [('http', '52.236.90.60:3128'), ('http', '165.225.20.14:10605'), ('http', '8.215.27.71:3128'), ('http', '103.155.54.245:84'), ('http', '183.245.6.120:8080')] """
* 1. 下载项目
项目地址: https://github.com/jhao104/proxy_pool
* 2. 解压并打来项目
* 3. 安装依赖: pip install -r requirements.txt
# 安装不上就换成国内源
APScheduler==3.2.0 # 定时任务框架
werkzeug==0.15.5 # Python的WSGI规范的实用函数库
Flask==1.0
requests==2.20.0
click==7.0 # 用于快速创建命令行
gunicorn==19.9.0 # Python WSGI UNIX的HTTP服务器
lxml # lxml是XML和HTML的解析器
redis
* 4. 更新配置(配置好redis库即可)
# setting.py 为项目配置文件 # 配置API服务 HOST = "0.0.0.0" # IP PORT = 5010 # 监听端口 # 配置数据库 DB_CONN = 'redis://:127.0.0.1:6379/0' # 配置 ProxyFetcher PROXY_FETCHER = [ "freeProxy01", # 这里是启用的代理抓取方法名,所有fetch方法位于fetcher/proxyFetcher.py "freeProxy02", # .... ]
* 5. 启动项目
如果已经具备运行条件, 可用通过proxyPool.py启动
程序分为: schedule 调度程序 和 server Api服务
# 都在Terminal 中输入命令
# 1. 启动调度程序(获取免费代理)
python proxyPool.py schedule
# 2. 启动webApi服务
python proxyPool.py server
启动报错:(更新 Flask Jinja2)
pip uninstall Flask Jinja2
pip install Flask Jinja2
启动调度后获取免费代理
* 6. 测试
* 7. 随机获取一个请求
* 8. 请求api介绍
启动web服务后, 默认配置下会开启 http://127.0.0.1:5010 的api接口服务:
api | method | Description | params |
---|---|---|---|
/ | GET | api介绍 | None |
/get | GET | 随机获取一个代理 | 可选参数: ?type=https 过滤支持https的代理 |
/pop | GET | 获取并删除一个代理 | 可选参数: ?type=https 过滤支持https的代理 |
/all | GET | 获取所有代理 | 可选参数: ?type=https 过滤支持https的代理 |
/count | GET | 查看代理数量 | None |
/delete | GET | 删除代理 | ?proxy=host:ip |
* 删除代理 ?proxy=host:ip ==> 官方文旦写的不好理解了,应该是 ?proxy=ip:port
* 9. 新建一个项目, 在项目中使用
import requests # 获取代理 def get_proxy(): # 后端发送的是json格式数据, 转为字段 return requests.get("http://127.0.0.1:5010/get/").json() # 删除代理 def delete_proxy(proxy): # 删除代理请求, 请求中携带删除的代理ip # http://127.0.0.1:5010/delete/?proxy=211.139.26.16:80 requests.get("http://127.0.0.1:5010/delete/?proxy={}".format(proxy)) # 使用代理获取网页 def getHtml(): # 重试次数 retry_count = 5 # 从字典中获取代理 proxy = get_proxy().get("proxy") # print(proxy) # 194.233.77.110:1111 while retry_count > 0: # 代理使用出错会抛出异常 try: html = requests.get('http://www.baidu.com', proxies={"http": "http://{}".format(proxy)}) # 使用代理访问 return html except Exception: retry_count -= 1 # 5次删除代理池中代理 delete_proxy(proxy) return None # 执行函数 html = getHtml() print(html.status_code) # 200
只演示图片验证码:
* 1. 将验证码下载到本地
* 2. 将验证码上传到打码平台(将图片验证码给别人识别, 全国有几十台服务器, 有六千多工人, 24小时轮班...)
* 3. 打码平台放回验证码
验证码识别平台: http://www.chaojiying.com/
* 1. 注册一个账户
* 2. 下载Demo实例代码包
* 3. 解压代码包
Chaojiying_Python
|-a.jpg 验证码图片
|-chaojiying.py 实例代码
* 4. 生成软件id
* 5. 获取积分
* 6. 打开项目测试
#!/usr/bin/env python # coding:utf-8 import requests from hashlib import md5 # 定义类 class Chaojiying_Client(object): # 实例化生成用户信息与请求头信息 def __init__(self, username, password, soft_id): # 用户 self.username = username # 密码解码 password = password.encode('utf8') # 加密密码 self.password = md5(password).hexdigest() # 应用id self.soft_id = soft_id # 基本参数 self.base_params = { 'user': self.username, 'pass2': self.password, 'softid': self.soft_id, } # 请求头信息 self.headers = { 'Connection': 'Keep-Alive', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', } # 将验证码图片发送到打码平台识别 def PostPic(self, im, codetype): """ im: 图片字节 codetype: 题目类型 参考 http://www.chaojiying.com/price.html """ # 图片的类型 params = { 'codetype': codetype, } # 将用户基本信息与请求头信息写入字典中 params.update(self.base_params) # 读取图片 files = {'userfile': ('ccc.jpg', im)} # 发送请求到打码平台 r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) # 返回一个json格式字典数据, 解码 return r.json() # 将验证码图片发送到打码平台识别 base64格式数据 def PostPic_base64(self, base64_str, codetype): """ im: 图片字节 codetype: 题目类型 参考 http://www.chaojiying.com/price.html """ params = { 'codetype': codetype, 'file_base64': base64_str } params.update(self.base_params) r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers) return r.json() # 异常信息 def ReportError(self, im_id): """ im_id:报错题目的图片ID """ params = { 'id': im_id, } params.update(self.base_params) r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) return r.json() if __name__ == '__main__': # 生成对象 chaojiying = Chaojiying_Client('q18177', 'q18177', '93518') # 用户中心>>软件ID 生成一个id替换 im = open('a.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要// print(chaojiying.PostPic(im, 1902)) # 1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加() # print chaojiying.PostPic(base64_str, 1902) #此处为传入 base64代码
* 7. 查看结果pic_str是验证码
* 1. 分析登入(输入一个错误的密码, 不然看不到请求就跳转了)
登入地址: http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F
获取验证码图片
* 这个网站的验证码就是不检验的,一下找不到合适的网站测试
import requests
from bs4 import BeautifulSoup
res = requests.get('http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F')
soup = BeautifulSoup(res.text, 'lxml')
# 获取图片地址
url = soup.find(id='login_img_checkcode')['src']
code_url = 'http://www.aa7a.cn/' + url
print(code_url)
* 2. 登入触发事件
数据提交地址: http://www.aa7a.cn/user.php
提交数据:
username: 1360012768@qq.com
password: zxc12dasdasd
captcha: asda
remember: 1
ref: http://www.aa7a.cn
act: act_login
import requests from bs4 import BeautifulSoup # 导入打码平台 from chaojiying import Chaojiying_Client res = requests.get('http://www.aa7a.cn/user.php?&ref=http%3A%2F%2Fwww.aa7a.cn%2F') soup = BeautifulSoup(res.text, 'lxml') # 获取图片地址 url = soup.find(id='login_img_checkcode')['src'] code_url = 'http://www.aa7a.cn/' + url # 获取验证码码 chaojiying = Chaojiying_Client('q18177354117', 'q18177354117', '935180') # 用户中心>>软件ID 生成一个替换 96001 # 保存图片 res = requests.get(code_url) code_dict = chaojiying.PostPic(res.content, 1902) print(code_dict.get('pic_str')) # data数据 data = { 'username': '1360012768@qq.com', 'password': 'zxc123456', 'captcha': code_dict.get('pic_str'), 'remember': 1, 'ref': 'http://www.aa7a.cn/', 'act': 'act_login', } # 登入 res = requests.post('http://www.aa7a.cn/user.php', data=data) print(res.text) # 登入成功显示: {"error":0,"ref":"http: // www.aa7a.cn"} # 登入失败显示: {"error":5}
* 1. 分析小说章节名称
地址: https://www.au26.com/shu/3414/
分析小说章节名称, 文章内容.
末尾还有两种广告!
* 2. 爬虫程序
import requests from bs4 import BeautifulSoup import re # 获取小说章节 res = requests.get('https://www.au26.com/shu/3414/') soup = BeautifulSoup(res.text, 'lxml') # 获取小说名称 name = soup.h1.text # 获取到id为list的节点 id_list = soup.find(id='list') # 排查广告标签 留下 <a href="/shu/3414/779395.html">第326章 完本感言</a> 这样的标签 chapter_re_href = re.compile(r'(.*?).html') chapter_re_text = re.compile(r'第\d+章.*') # 获取list下所有的a标签 list_a = id_list.find_all(href=chapter_re_href, text=chapter_re_text) # 去重并排序 [3, 2, 1, 2, 3, 4] -> [1, 2, 3, 4] chapter_list = [] for chapter in list_a: # 存在则更新 chapter 是Tag对象 不是字符串!!! if chapter in chapter_list: # 获取存在值的索引 index = chapter_list.index(chapter) # pop掉 chapter_list.pop(index) # 重新把值写在后面 chapter_list.append(chapter) chapter_list.append(chapter) print(chapter_list) # 写入txt with open(f'{name}.txt', mode='wt', encoding='utf-8') as wf: # chapter 是Tag对象 不是字符串!!! for chapter in chapter_list: # 章节名称 chapter_name = chapter.text # 章节地址 chapter_url = 'https://www.au26.com/' + chapter.get('href') # 章节内容 res = requests.get(chapter_url) soup = BeautifulSoup(res.text, 'lxml') # 获取content下的所有文本内容 content = soup.find(id='content').text # 剔除广告 str1 = '喜欢大明王侯请大家收藏:(www.au26.com)大明王侯笔趣阁备用站更新速度最快。 ' str2 = '&&ahref=http:www.&&;起点中文网www.欢迎广大书友光临阅读,最新、最快、最火的连载作品尽在起点原创!' pure_content = content.strip(str1).strip(str2) # 写入到txt中 wf.write(chapter_name + '\n') wf.write(pure_content + '\n')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。