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. 搭免费代理池
# 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()