爬虫的流程
分布式爬虫---》redis(blpop/brpop:列表,阻塞队列)
集群和分布式:以前都是单实例的项目
集群化的部署:一个项目部署在多台机器上
分布式(微服务):一个项目拆成多个部分,放到不同的服务器上,每个项目单独开发,单独上线
1 爬取汽车之家新闻(requests+bs4)
总结:
bs4 查找文档树
1 标签对象=soup.find(name='div',href='',class_='')
2 标签对象可以继续使用find
3 获取属性两种方式 标签对象['属性名'] 标签对象.attrs.get('属性名')
4 获取文本 标签对象.text
'''
爬取汽车之家新闻
pip3 install beautifulsoup4
pip3 install lxml
'''
import requests
#引入
from bs4 import BeautifulSoup
for i in range(1,10):
ret=requests.get('https://www.autohome.com.cn/news/%s/#liststart'%i)
ret.encoding='gbk'
# print(ret.text)
#实例化得到对象
#第一个参数是字符串或者是文件对象
#第二个参数,解析方式(html.parser lxml)
soup=BeautifulSoup(ret.text,'lxml')
#以后查找属性,都是操作soup这个对象
#查看文档树值查找所有
# div=soup.find_all(name='div',id='auto-channel-lazyload-article')[0]
#查找div下的ul标签
# ul=div.find_all(name='ul')
# print(ul)
#class是一个关键字
ul=soup.find(name='ul',class_='article')
#找到ul下所有的li标签
li_list=ul.find_all(name='li')
# print(li_list)
#循环列表
for li in li_list:
img=li.find(name='img')
if img:
# print(img)
#获取标签的属性两种方式
# img_ul=img['src']
img_ul='http:'+img.attrs.get('src')
# print(img_ul)
title=li.find(name='h3').text
# print(title)
desc=li.find(name='p').text
# print(desc)
url='http:'+li.find(name='a')['href']
# print(url)
#图片保存
# img_name=img_ul.rsplit('/',1)[-1]
# ret2=requests.get(img_ul)
# with open(img_name,'wb') as f:
# for line in ret2.iter_content():
# f.write(line)
print('''
文章标题:%s
文章链接:%s
文章图片地址:%s
文章摘要:%s
'''%(title,url,img_ul,desc))
2 beautifulsoup4的使用
#beautifulsoup4的使用
from bs4 import BeautifulSoup
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" id="xxx">文字文字<span>The Dormouse's story</span>
<b id="id_b">xxxxxxx</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
<p>我是内层p标签</p>
</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
#实例化对象的两种方式
soup=BeautifulSoup(html_doc,'lxml')
# soup=BeautifulSoup(open('a.html'),'lxml')
# 美化(了解)
# print(soup.prettify())
2.1 遍历文档树
# 遍历文档树
# 1 用法 直接用 . 取下一个标签
# 2 获取标签的名称
# 3 获取名称的属性
# 4 获取标签的内容
# 必须掌握
# head=soup.head
# print(head)
# p=soup.p
# print(p)
# p=soup.body.p
# print(p)只能找到一个
#获取标签的名字
# p=soup.body.p
# print(p.name)
#获取属性
#当获取class的时候 获取的是一个列表 因为class可以有多个
# p=soup.body.p
# print(p['class'])
# print(p['id'])
# print(p.attrs.get('class'))
# 获取内容
# text:获取所有的文字,包括子标签
# string: 获取当前第一级目录的文字,如果嵌套多层,就取不出文字
# strings:生成器,每一层的文字都放在里面
# p=soup.body.p
# print(p.text)
# print(p.string)
# print(p.strings)
# print(list(p.strings))
#用的比较少
# 5 嵌套选择
# 6 子节点 子孙节点
# print(soup.body.p.contents)
# print(list(soup.body.p.children))
# print(list(soup.body.p.descendants))#子子孙孙
# 7 父节点 祖先节点
# print(soup.body.p.parent)#直接父节点
# print(list(soup.body.p.parents))#父亲 父亲的父亲 全部放到生成器中
# 8 兄弟节点
# print(soup.a.next_sibling)#下一个兄弟标签
# print(soup.a.previous_sibling)#上一个兄弟
2.2 查找文档树
# 搜索文档树
# 搜索的查找速度比遍历低
# find find_all
# 字符串 列表 正则 True 方法
# 字符串:精准匹配
#p是标签对象 跟soup是一样的
# p=soup.find(name='p',class_='story')
# print(p)
# b=soup.find(name='b')
# print(b)
#通过属性查找的方式一
# b=soup.find(id='id_b')
# print(b)
#通过属性查找的方式二
# b=soup.find(attrs={'id':'id_b'})
# p=soup.find(attrs={'class':'story'})
# print(p)
#列表查找
# ret=soup.find_all(name=['p','b'])
# ret=soup.find_all(id=['id_b','link1'])
# print(ret)
#正则
import re
#查找名字以b开头的标签
# ret=soup.find_all(name=re.compile('^b'))
# ret=soup.find_all(id=re.compile('^l'))
# print(ret)
# True
#查找所有有id的标签
# ret=soup.find_all(id=True)
# ret=soup.find_all(name=True)
# print(ret)
# 方法
# def has_class_but_no_id(tag):
# return tag.has_attr('class') and not tag.has_attr('id')
# ret=soup.find_all(has_class_but_no_id)
# print(ret)
# 取属性 取文字
# tag对象['src'] tag对象.attrs.get('src')
# tag对象.text string
#遍历文档树 和 搜索文档树可以同时使用
# soup.body.find(name='p').b
# soup.body.find(name='p').find()
# print(type(soup))
# Tag对象用起来跟BeautifulSoup对象用起来完全一样
#body=soup.body
# print(type(body))
# 拓展 链式调用(跟语言没关系,jq)
# 链式调用在python中如何实现?点多少次,其实还是对象本身
# class A:
# def test(self,name):
# self.name=name
# return self
# def test2(self,age):
# self.age=age
# return self
# a=A()
# a.test('lqz').test2(19)
# print(a.age)
# bs4 其他用法
#limit 限制查找的个数
# ret=soup.find_all(name='p',limit=1)
# print(ret)
# soup.find_all()
# recursive 是否递归查找 默认是True
# ret=soup.body.find_all(name='p',recursive=False)
# ret2=soup.body.find_all(name='p',recursive=True)
# print(len(ret))
# print(len(ret2))
2.3 css选择
# css选择
# select 方法中写css选择器
# ret=soup.select('.title')
# ret=soup.select('#id_b')
#这两的区别 儿子和子孙的区别
# ret=soup.select('.title>b')
# ret=soup.select('.title b')
# print(ret)
# 重点 > 和 空格的区别
# > 选择直接的子元素
# 选取子子孙孙
2.4 xpath选择(beautifulsoup4没有xpath选择)
3 爬取三国演义小说
4 代理池(免费代理、收费代理)
收费
免费
https://github.com/jhao104/proxy_pool
自己搭建:flask框架搭建服务,后台用爬虫(requests爬取免费),放入redis
127.0.0.1/get 随机给我一个代理ip
网上开源的:proxy_pool项目部署
#1 下载下来,打开
#2 安装依赖 pip3 install -r requirements.txt
#3 修改配置文件Config/setting.py
35行左右,意思是爬取的代理放到redis中,
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 跑项目 可以在cli目录下通过ProxyPool.py启
python3 proxyPool.py schedule:爬取代理
python3 proxyPool.py webserver:启动服务
#5 测试
http://127.0.0.1:5010/get/ 发一次,取一个代理ip
自己爬的100条 99条不能用 定时测试能不能用 用代理去访问一个网址
验证码破解(打码平台)
花钱,从网上的验证码图片,传给它,他就给你识别,(12306的验证码,模拟登陆12306)
-超级鹰
-模拟登陆某些网站
-http://www.chaojiying.com/price.html
# 注册用户
# 创建软件
# 充值
# 下载demo
# 修改demo,账号密码该上
# 运行代码
-云打码
补充:python调用dll文件
跟华为合作 ,华为摄像头的硬件设备,Windows,用软件
用python来调用,可以操控摄像头,给了他们一个文档(熟悉一门桌面开发语言,Tkinter,pyqt),华为提供了SDK(别人写好的低包),只需要python来调用,华为提供的不是python写的sdk,xxx.dll这种东西,动态链接库,C语言写的(Windows中每个软件都会有dll文件)