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 = """
页面标题
标题
...
"""
soup = BeautifulSoup(html_doc, 'lxml') # 具有容错功能
res = soup.prettify() # 处理好缩进, 结构化显示
print(res)
遍历文档树: 即直接通过标签名字选择, 特点是选择速度快, 但如果存在多个相同的标签则只返回第一个.
* 多个相同标签只返回第一个, 第一个算遍历, 其他的都不算!
soup = BeautifulSoup(html_doc, 'lxml')
# 与.find()方法速度一致
print(soup.p) # 标题
# 值是提供Tag对象
# 推荐方法(速度快)
print(soup.body.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) #
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)) # 标题
* 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>iptd>
<td>端口号td>
<td>代理位置td>
<td>代理类型td>
<td>验证时间td>
tr>
<tr>
<td>165.225.20.14td>
<td>10605td>
<td>宁夏回族自治区中卫市td>
<td>高匿代理td>
<td>2022年06月17日06时 验证td>
tr>
<tr>
<td>8.215.27.71td>
<td>3128td>
<td>吉林省辽源市td>
<td>高匿代理td>
<td>2022年06月17日04时 验证td>
tr>
<tr>
<td>103.155.54.245td>
<td>84td>
<td>广西壮族自治区桂林市td>
<td>高匿代理td>
<td>2022年06月17日02时 验证td>
tr>
<tr>
<td>183.245.6.120td>
<td>8080td>
<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'>-->
<tr>
<td>iptd>
<td>端口号td>
<td>代理位置td>
<td>代理类型td>
<td>验证时间td>
tr>
<tr>
<td>165.225.20.14td>
<td>10605td>
<td>宁夏回族自治区中卫市td>
<td>高匿代理td>
<td>2022年06月17日06时 验证td>
tr>
<tr>
<td>8.215.27.71td>
<td>3128td>
<td>吉林省辽源市td>
<td>高匿代理td>
<td>2022年06月17日04时 验证td>
tr>
<tr>
<td>103.155.54.245td>
<td>84td>
<td>广西壮族自治区桂林市td>
<td>高匿代理td>
<td>2022年06月17日02时 验证td>
tr>
<tr>
<td>183.245.6.120td>
<td>8080td>
<td>云南省保山市td>
<td>高匿代理td>
<td>2022年06月17日00时 验证td>
tr>
* 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>iptd>
<td>端口号td>
<td>代理位置td>
<td>代理类型td>
<td>验证时间td>
----
<td>165.225.20.14td>
<td>10605td>
<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': '[email protected]',
'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')
# 排查广告标签 留下 第326章 完本感言 这样的标签
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')