数据:国家统计局官网|环球网
微信公众号合作方:https://weixin.sogou.com/
百度搜索资源平台:https://ziyuan.baidu.com/robots/index
json在线解析: https://www.bejson.com/
python安装第三方模块
- pip install
- 源码包
下载源码包 – 解压缩源码包 –python setup.py install
***.whl
安装pip install ***.whl
注意事项
注意: 手机版的页面内容只能在 F12 调试模式下,查看response响应的内容!!!
一、通用爬虫模块
- 模拟浏览器发送请求
- 爬虫更多用途:
- 12306抢票|
- 网站上的投票|
- 短信轰炸
爬虫的流程
- 爬虫分类:
- 通用爬虫:通常指搜索引擎爬虫
- 聚焦爬虫:针对特定网站爬虫
重点关注
通用搜索引擎工作原理
搜索引擎的工作原理及robots协议
爬虫介绍
种子URL
robots协议
:当前网站的根目录下面有个 robots.txt 文件
http://baidu.com/ robots.txt
User-agent: Baiduspider
Disallow: /baidu
Disallow: /s?
Disallow: /ulink?
Disallow: /link?
Disallow: /home/news/data/
Disallow: /bh
....
....
....
User-agent: *
Disallow: /
了解浏览器发送请求的流程
爬虫要根据当前url对应的响应为准,当前url地址的elements的内容和url的响应不一样
浏览器渲染出来的页面和爬虫请求的页面是不一样的
问:页面上的数据在哪里?
- 当前url地址对应的响应中
- 其他的url地址对应的响应中
- ajax 请求中
- js生成的
- 部分数据在响应中
- 全部js生成
URL的形式
形式 scheme://host[:port]/path/…/[?query-string][#amchor]
scheme 协议(eg:http、https、ftp)
host 服务器的Ip地址或域名
port 服务器的端口(如果是走协议默认端口,80 or 443)
path 访问资源的路径
query-string 参数,发送给http服务器的数据
amchor 锚点(跳转到网页指定锚点位置)
HTTP 常见的请求头
HOST 主机和端口号
Connection 链接类型
Upgrade-Insecure-Requests 升级为HTTPS请求
User_Agent 浏览器名称
Accept 传输文件类型
Referer 页面跳转处
Accept-Encoding 文件编码格式
Cookie
x-requested-with:XMLHttpRequest(是Ajax异步请求)
常见状态码详解
字符串类型的区别和转化
bytes:二进制(互联网上的数据都是以二进制的数据传输的)
str:unicode的形式展现
encode
decode
字符串格式化方式
"啦啦啦{}kdlkf{}".format("你好啊")
% 方式
url = ‘https://www.baidu.com/s?wd={}’.format(“查询”)
爬虫 requests 库
# coding=utf-8
import requests
kw = input("enter a word:")
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
p = {
'wd': kw
}
url = 'https://www.baidu.com/s?'
response = requests.get(url=url, params=p, headers=headers)
# print(response.text)
print(response.status_code)
print(response.headers)
print(response.request)
print(response.request.headers)
print(response.content)
贴吧爬虫
request模块发送post请求
import requests
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
post_data = {
"form":"en",
"to":"zh",
"query":"人生苦短"
}
post_url = "https://fanyi.baidu.com/v2transapi"
r=requests.post(post_url,data=post_data,headers=headers)
requests模块使用代理
正向代理和反向代理的区别:是否知道最终请求服务器的地址!!!
-
用法:requests.get(url,proxies = proxies,headers=headers)
proxies 的形式:字典proxies = {
“http”:“”,
“https”:“”
} -
注意
- 准备一堆的ip地址,组成ip池,随机选择一个IP来用
- 如何随机选择代理IP
- {“ip”:ip,“times”:0}
- [{},{},{},{},{}] 对这个ip列表进行排序,按照使用次数进行排序
- 选择较少的使用次数的10个IP,从中随机选择一个
- 检查ip的可用性
- 可以使用 request 添加超时参数,判断ip质量
- 在线代理ip检测网站
-
问:为什么爬虫需要代理?
- 让服务器以为不是同一个客户端请求
- 防止我们的真实地址被披露,防止被追究
-
代理
[米扑代理]https://proxy.mimvp.com/
[码农很忙]https://www.coderbusy.com/archives/2616.html
requests 模拟登录的三种方式
requests 提供了一个叫做session类,来实现客户端和服务端的会话保持
session = requests.session()
response = session.get(post_url,headers=headers)
获取登录后页面的三种方式
- 实例化 session,使用session发送post请求,再使用他获取登录后的页面
- headers 中添加cookie键,值为cookie字符串
- 在请求方法中添加cookies参数,接收字典形式的cookie,字典形式的cookie中的键式cookie的name对应的值,value是 cookie value的值
手动尝试使用session来登录人人网 : http://www.renren.com/Plogin.do
- 携带cookie请求
- 携带cookie进行请求,把cookie组成cookie池
- 使用requests请求登录之后的网站的思路
- 实力化session
- 先使用session发送请求,登录网站,把cookie保存在session中
- 在使用session请求登录之后才能访问的网站,session能勾自动携带登录成功时保存在其中的cookie进行请求
import requests
post_url = ""
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
post_data = {}
session = requests.session()
session.post(post_url,data=post_data,headers=headers)
session.get(post_url,headers=headers)
- 不发送post请求,使用cookie获取登录后的页面
- cookies 过期时间很长
- 在cookie过期之前能够拿到所有的数据,比较麻烦
- 配合其他程序一起使用,其他程序专门获取cookie,当前程序专门请求页面
url = ""
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36',
'Cookie':''
}
requests.get(url=url, headers=headers)
字典推导式,列表推导式
# 字典
cookies="PSTM=1605247706; BIDUPSID=4453E13A228BDA1DB2E813221E502E36; __yjs_duid=1_a9f37727459fde17b5309351fa92907b1618563331437; BDUSS=0ySXhkZ0VZYk44Sm5icVRaWHd5M3BNV1NlYzdKTHhqZmVKNjlhdnBkbzI1S0JnRVFBQUFBJCQAAAAAAAAAAAEAAAA-rzyWenp6d3d3OTk4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADZXeWA2V3lgQS; "
cookies={i.split("=")[0]:i.split("=")[1] for i in cookies.split("; ")}
url = ""
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
}
requests.get(url, headers=headers,cookies=cookies)
# 列表
[self.url.format(i+50) for i in range(1000)]
requests 模块发送请求和获取网页的字符串[中解决编解码的方法]
pip install requests
pip --version 查看版本号
- request 中解决编解码的方法
response.content.decode()
response.content.decode(‘gbk’)
response.text
request 小技巧
-
requests.util.dict_from_cookiejar 把cookie对象转化为字典
-
url 编码解码
requests.util.quote
requests.util.unquote -
请求SSL证书验证
response = requests.get(“https://www.12306.cn/mormhweb/”,verify=False) -
设置超时
response = requests.get(url,timeout=10) -
配合状态码判断是否请求成功
assert response.status_code == 200 -
pip install retrying
装饰器的方式使用:执行3次,程序报错
@retry(stop_max_attemp_number=3)
爬虫数据 - json数据
数据分类
- 结构化数据 json、xml : 处理方法转化为 python 数据类型
- 非结构化数据 html : 处理方法正则表达式/xpath
json模块学习
JSON(javascript object notation)轻量级的数据交换格式
问:哪里找到返回json的URL?
- chrome切换到手机版
- 抓包手机app的软件
import json
# 将 Python 对象编码成 JSON 字符串
json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)
# 将已编码的 JSON 字符串解码为 Python 对象
json.loads(s[, encoding[, cls[, object_hook[, parse_float[, parse_int[, parse_constant[, object_pairs_hook[, **kw]]]]]]]])
-
json中字符串都是双引号
-
-
如果不是双引号
- eval :能实现简单的字符串和python类型的转换
- replace :把单引号转换为双引号
数据提取
-
json字符串
- json_loads()
- json_dumps() 包含json的类文件对象
- json.load()
- json.dump()
注:只有read()或者write()方法的对象就是类文件对象
f=open(“json.txt”,“r”) f 就是类文件对象
- 往一个文件中写入多个json串,不再是一个json,不能直接读取
- 一行写一个json按照行来读取
- 一行写一个json按照行来读取
正则处理数据[regular expression]
正则和原始字符串 r
-
常用正则表达式的方法:
- re.compile(编译)
- pattern.match(从头找一个)
- pattern.search(找一个)
-
pattern.findall(找所有)
re.findall(".","\n",re.S)
re.S 等价 re.DOTALL
不分组时匹配的是全部,分组后匹配的是组内内容
- pattern.sub(替换)
r
的使用
-
忽略转译字符带来的转译的影响
r"a\nb" == “a\nb” False
re.findall(“a\nb”,“a\nb”)
re.findall(r"a\nb",“a\nb”)
re.findall(“a\nb”,“a\nb”) -
windows 下不使用原始字符串会出现问题
r’D:\my\soft’
正则使用的注意点
- re.findall(“a(.*?)b”,“str”) 能够返回括号中的内容,括号前后的内容起到定位和过滤的效果
- 原始字符串
r
,待匹配字符串中有反斜杠的时候,使用它能够忽视反斜杠带来的转译效果 - 点号默认情况匹配不到
\n
\s
能够匹配空白字符,不仅仅包含空格,还有\t|\r\n
xpath处理数据
xml 了解
XPATH和LXML类库
http://www.w3school.com.cn/xpath/index.asp
数据格式 | 描述 | 设计目标 |
---|---|---|
xml | EXtensible Markup Language(可扩展标记语言) | 被设计为传输和存储数据,其焦点是数据的内容 |
HTML | HyperText Markup Language(超文本标记语言) | 显示数据以及如何更好的显示数据 |
<book> parent
<title></title> children
<author></author> sibling
<year></year> Ancestor
<price></price> Descendant
</book>
-
工具
- google 插件 XPath Helper
- 开源Xpath表达式编辑工具:XMLQuire(XML文件格式可用)
- Firefox 插件 XPath Checker
xpath学习重点
- 获取文本
a/text()
获取a下的文本a//text()
获取a下所有标签的文本//a[text()=='下一页']
选择文本下一页为三个字的a标签
@
a/@href
获取属性//url[@id="detail-list"]
//
- 在xpath开始的时候表示从当前html中任意位置开始选择
li//a
表示的是li下任何一个标签
*** 注意:使用xpath helper 或者是 chrome 中的 copy xpath 都是从element中提取的数据,但爬虫获取的是url对应的响应,往往和 elements不一样
***
lxml 库
-
使用入门
- 导入lxml的etree库
from lxml import etree - 利用etree.HTML,将字符串转化为Element对象
- Element对象具有xpath的方法
html=etree.HTML(text)
- 导入lxml的etree库
-
lxml可以自动修正 html代码
-
lxml能够接受bytes和str的字符串
-
提取页面数据的思路
- 先分组
- 遍历,取其中每一组进行数据的提取,不会造成数据的对应错乱
通用爬虫的套路
- 准备 url
- 准备 start_url
- url 地址规律不明显,总数不确定
- 通过代码提取下一页URL
- xpath
- 寻找 url 地址,部分参数在当前响应中(比如,当前页码数和总的页码数在当前的响应中)
- 准备 url_list
- 页码总数明确
- URL地址规律明显
- 准备 start_url
- 发送请求,获取响应
- 添加随机的
User-Agent
,反反爬虫 - 添加随机的代理
IP
,反反爬虫 - 在对方判断出我们是爬虫之后,应该添加更多的
header
字段,包括cookie - cookie的处理可以使用session来解决
- 准备一堆能用的cookie,组成cookie池
- 如果不登录
- 准备刚开始能够成功请求对方网站的cookie,即接收对方网站设置在response的cookie
- 下次请求的时候,使用之前的列表中的cookie来请求
- 如果登录
- 准备多个账号
- 使用程序获取每个账号的cookie
- 之后请求登录之后才能访问的网站随机的选择cookie
- 如果不登录
- 添加随机的
- 提取数据
- 确定数据的位置
- 如果数据在当前页面的url地址中
- 提取的是列表页的数据
- 直接请求列表页的URL地址,不用进入详情页
- 提取详情页的数据
-
- 确定url
-
- 发送请求
-
- 提取数据
-
- 返回
-
- 提取的是列表页的数据
- 如果数据不在当前URL地址中
- 在其他响应中,寻找数据的位置
-
- 从 network 中从上往下寻找
-
- 使用chrome中过滤条件,选择除了 js ,css , img 之外的按钮
-
- 使用chrome的search all file,搜索数字和英文
-
- 在其他响应中,寻找数据的位置
- 如果数据在当前页面的url地址中
- 数据提取
- xpath,从html中提取整块的数据,先分组,之后每一组再提取
- re,提取 max_time,price,html中的json字符串
- json
- 确定数据的位置
- 保存
- 保存在本地,text、 json、csv
- 保存在数据库