bs4解析html与xml、代理池、验证码破解

bs4解析html与xml、代理池、验证码破解

1. bs4模块使用

bs4是用来解析xml或者html的

下载:pip3 install beautifulsoup4

from bs4 import BeautifulSoup
# 可以使用html.parser(稍慢)解析或者lxml解析(需要下载) pip3 install lxml
# 实例化对象(传入要解析的文本,解析器)
soup = BeautifulSoup(ret.text, 'html.parser')
soup.prettify()  # 美化

1. 遍历文档树

from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"id="id_p"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story">...</p>
"""

soup = BeautifulSoup(html_doc, 'lxml')
# 1 通过 . 来查找,只能找到第一个
a = soup.a # 得到Tag对象
print(a)
print(a.text)  # Elsie

# 2 获取标签名(没什么卵用)
# Tag对象
p = soup.body
print(p.name) # body


# 3 获取标签的属性
p = soup.p
# 方式1: 直接中括号获取或者get获取
# 获取的class属性,可以有多个,所以是列表
print(p['class'])  # ['title']
print(p['id'])  # id_p
print(p.get('id'))  # id_p

# 方式2:attrs[]或是attrs.get
print(p.attrs['class'])  # ['title']
print(p.attrs.get('id'))  # id_p


# 4 获取标签内容
p = soup.p
print(p.text)  # 拿所有
print(p.string)  # 仅拿第一层
print(list(p.strings))  # 每次取出做一个生成器


# 5 嵌套选择
title = soup.head.title
print(title)


# 6 子节点与子孙节点
p1 = soup.p.children  # 获取一个子节点,得到迭代器
p2 = soup.p.contents  # 获取所有子孙,得到列表
print(list(p1))
print(p2)


# 7 父节点与祖先节点
p1 = soup.p.parent  # 直接父节点
p2 = soup.p.parents  # 生成器
print(p1)
print(list(p2))


# 8 兄弟节点
print(soup.a.next_sibling) #下一个兄弟
print(soup.a.previous_sibling) #上一个兄弟

print(list(soup.a.next_siblings)) #下面的兄弟们=>生成器对象
print(soup.a.previous_siblings) #上面的兄弟们=>生成器对象

2. 查找文档树

主要用 find,find_all 速度比遍历文档树快,可以两个配合使用

五种过滤器:字符串、正则表达式、列表、True、方法

# 1 字符串查找 引号内是字符串
p = soup.find(name='p')
a = soup.find(name='a')
# 查找类名是title的所有标签,class是关键字,所有用class_
ret = soup.find_all(class_='title')
# 查找href属性为http://example.com/elsie的标签
res = soup.find_all(href='http://example.com/elsie')
# 查找id为xx的标签
id = soup.find_all(id='id_p')


# 2 正则表达式
import re
# 查找以b开头的标签
reg = re.compile('^b')
ret = soup.find_all(name=reg)


# 3 列表 or关系
ret = soup.find_all(name=['body', 'b'])
res = soup.find_all(id=['id_p', 'link1'])

# and关系有,
ret = soup.find_all(class_='title', name='p')
print(ret)


# 4 True # 获取所有
# 所有有名字的标签
ret=soup.find_all(name=True)
# 所有有id的标签
ret=soup.find_all(id=True)
# 所有有herf属性的
ret=soup.find_all(href=True)
print(ret)


# 5 方法
def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

print(soup.find_all(has_class_but_no_id))


# 6 其他使用
ret=soup.find_all(attrs={'class':"title"})
ret=soup.find_all(attrs={'id':"id_p1",'class':'title'})
print(ret)

# 7 拿到标签,取属性,取text
ret=soup.find_all(attrs={'id':"id_p",'class':'title'})
print(ret[0].text)

# 8 limit(限制条数)
soup.find()    # 就是find_all limit=1
ret=soup.find_all(name=True,limit=2)
print(len(ret))

# 9 recursive
recursive=False  # (只找儿子)不递归查找,只找第一层
ret=soup.body.find_all(name='p',recursive=False)
print(ret)

3. 爬取汽车之家新闻练习

import requests
ret = requests.get('https://www.autohome.com.cn/all/1/#liststart')
# print(ret.text)
# ret.encoding='gb2312'  # 没有乱码可以不改

# bs4解析
from bs4 import BeautifulSoup
# 可以使用html.parser(稍慢)解析或者lxml解析(需要下载)
soup = BeautifulSoup(ret.text, 'html.parser')
# find_all找到所有的li, 得到列表
li_list =soup.find_all(name='li')
for li in li_list:
    # li/h3 是 Tag对象
    h3 = li.find(name='h3')
    # 去除找到的所有li中的无效的li
    if not h3:
        continue
    title = h3.text
    desc = li.find(name='p').text
    # 获取连接用[]取值
    img = li.find(name='img')['src'] # type:str
    url = li.find(name='a')['href']
    img_url = requests.get('https:'+img)
    img_name = img.rsplit('/',1)[-1]
    # 将图片下载到本地
    with open(f'E:\crawler\img\{img_name}','wb') as f:
        for line in img_url.iter_content():
            f.write(line)
    print('ok')
    # print('''
    # 新闻标题:%s
    # 新闻摘要:%s
    # 新闻链接:%s
    # 新闻图片:%s
    # '''%(title,desc,url,img))

2. 搭免费代理池

从Github上找开源的项目使用

# https://github.com/jhao104/proxy_pool
# 收费的:提供给你一个接口,每掉一次这个接口,获得一个代理
# 免费:用爬虫爬取,免费代理,放到我的库中,flask,django搭一个服务(删除代理,自动测试代理可用性),每次发一个请求,获取一个代理

# 带你配置

# 1 下载,解压,用pycharm打开
# 2 安装依赖 pip install -r requirements.txt
# 3 配置Config/setting.py:
    DB_TYPE = getenv('db_type', 'redis').upper()
    DB_HOST = getenv('db_host', '127.0.0.1')
    DB_PORT = getenv('db_port', 6379)
    DB_PASSWORD = getenv('db_password', '')
# 4 本地启动redis-server

# 5 可以在cli目录下通过ProxyPool.py
    -python proxyPool.py schedule :调度程序,他会取自动爬取免费代理
  -python proxyPool.py webserver:启动api服务,把flask启动起来

3. 验证码破解

# 打码平台(自动破解验证码,需要花钱)云打码,超级鹰(12306)
http://www.yundama.com/
http://www.chaojiying.com/

# 注册账号,(充钱)把demo下载下来,运行即可

4. 爬取糗事百科,微信自动发送

# 爬糗事段子
import requests
from bs4 import BeautifulSoup
ret = requests.get('https://www.qiushibaike.com/text/')
# print(ret.text)  # 得到的是html格式的数,所以我们使用bs4解析
l1 = []
soup = BeautifulSoup(ret.text, 'lxml')
article_list = soup.find_all(name='div', class_='article')
# print(article_list)
for article in article_list:
    content = article.find(name='div', class_='content').span.text
    l1.append(content)
print(l1)

# 微信自动发送消息
# wxpy:实现了web微信的接口
# pip3 install wxpy
from wxpy import *
# 实例化得到一个对象,微信机器人对象
import random
bot=Bot(cache_path=True)

@bot.register() # 接收从指定好友发来的消息,发送者即recv_msg.sender为指定好友girl_friend
def recv_send_msg(recv_msg):
    print('收到的消息:',recv_msg.text) # recv_msg.text取得文本
    return random.choice(l1)

embed()

 

posted @ 2020-04-09 00:00  Mr沈  阅读(401)  评论(0编辑  收藏  举报