# 0 爬虫准备工作
- 参考资料
- python网络数据采集, 图灵工业出版
- 精通Python爬虫框架Scrapy, 人民邮电出版社
- [Python3网络爬虫](http://blog.csdn.net/c406495762/article/details/72858983)
- [Scrapy官方教程](http://scrapy-chs.readthedocs.io/zh_CN/0.24/intro/tutorial.html)
- 前提知识
- url
- http协议
- web前端,html, css, js
- ajax
- re, xpath
- xml
# 1. 爬虫简介
- 爬虫定义:网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),
是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。
另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
- 两大特征
- 能按作者要求下载数据或者内容
- 能自动在网络上流窜
- 三大步骤:
- 下载网页
- 提取正确的信息
- 根据一定规则自动跳到另外的网页上执行上两步内容
- 爬虫分类
- 通用爬虫
- 专用爬虫(聚焦爬虫)
- Python网络包简介
- Python2.x:urllib, urllib2, urllib3, httplib, httplib2, requests
- Python3.x: urllib, urllib3, httplib2, requests
- python2: urllib和urllib2配合使用,或者requests
- Python3: urllib,requests
# 2. urllib
- 包含模块
- urllib.request: 打开和读取urls
- urllib.error: 包含urllib.request产生的常见的错误,使用try捕捉
- urllib.parse: 包含解析url的方法
- urllib.robotparse: 解析robots.txt文件
- 案例v1
from urllib import request
'''
使用urllib.request请求一个网页内容,并把内容打印出来
'''
if __name__ == '__main__':
url = "http://jobs.zhaopin.com/195435110251173.htm?ssidkey=y&ss=409&ff=03&sg=2644e782b8b143419956320b22910c91&so=1"
# 打开相应url并把相应页面作为返回
rsp = request.urlopen(url)
# 把返回结果读取出来
# 读取出来内容类型为bytes
html = rsp.read()
print(type(html))
# 如果想把bytes内容转换成字符串,需要解码
html = html.decode("utf-8")
print(html)
- 网页编码问题解决
- chardet 可以自动检测页面文件的编码格式,但是,可能有误
- 需要安装, conda install chardet
- 案例v2
'''
利用request下载页面
自动检测页面编码
'''
import urllib
import chardet
if __name__ == '__main__':
url = 'http://stock.eastmoney.com/news/1407,20170807763593890.html'
rsp = urllib.request.urlopen(url)
html = rsp.read()
#利用 chardet自动检测
cs = chardet.detect(html)
print(type(cs))
print(cs)
# 使用get取值保证不会出错
html = html.decode(cs.get("encoding", "utf-8"))
print(html)
- urlopen 的返回对象
- 案例v3
import urllib
if __name__ == '__main__':
url = 'http://stock.eastmoney.com/news/1407,20170807763593890.html'
rsp = urllib.request.urlopen(url)
print(type(rsp))
print(rsp)
print("URL: {0}".format( rsp.geturl()))
print("Info: {0}".format(rsp.info()))
print("Code: {0}".format(rsp.getcode()))
html = rsp.read()
# 使用get取值保证不会出错
html = html.decode()
- geturl: 返回请求对象的url
- info: 请求反馈对象的meta信息
- getcode:返回的http code
- request.data 的使用
- 访问网络的两种方法
- get:
- 利用参数给服务器传递信息,
- 参数为dict,然后用parse编码
- 案例v4
from urllib import request, parse
'''
掌握对url进行参数编码的方法
需要使用parse模块
'''
if __name__ == '__main__':
url = 'http://www.baidu.com/s?'
wd = input("Input your keyword:")
# 要想使用data, 需要使用字典结构
qs = {
"wd": wd
}
# 转换url编码
qs = parse.urlencode(qs)
print(qs)
fullurl = url + qs
print(fullurl)
# 如果直接用可读的带参数的url,是不能访问的
#fullurl = 'http://www.baidu.com/s?wd=大熊猫'
rsp = request.urlopen(fullurl)
html = rsp.read()
# 使用get取值保证不会出错
html = html.decode()
print(html)
- post
- 一般向服务器传递参数使用
- post是把信息自动加密处理
- 我们如果想使用psot信息,需要用到data参数
- 使用post,意味着Http的请求头可能需要更改:
- Content-Type: application/x-www.form-urlencode
- Content-Length: 数据长度
- 简而言之,一旦更改请求方法,请注意其他请求头部信息相适应
- urllib.parse.urlencode可以将字符串自动转换成上面的
- 案例v5
'''
利用parse模块模拟post请求
分析百度词典
分析步骤:
1. 打开F12
2. 尝试输入单词girl,发现每敲一个字母后都有请求
3. 请求地址是 http://fanyi.baidu.com/sug
4. 利用NetWork-All-Hearders,查看,发现FormData的值是 kw:girl
5. 检查返回内容格式,发现返回的是json格式内容==>需要用到json包
'''
from urllib import request, parse
# 负责处理json格式的模块
import json
'''
大致流程是:
1. 利用data构造内容,然后urlopen打开
2. 返回一个json格式的结果
3. 结果就应该是girl的释义
'''
baseurl = 'http://fanyi.baidu.com/sug'
# 存放用来模拟form的数据一定是dict格式
data = {
# girl是翻译输入的英文内容,应该是由用户输入,此处使用硬编码
'kw': 'girl'
}
# 需要使用parse模块对data进行编码
data = parse.urlencode(data).encode("utf-8")
print(type(data))
# 我们需要构造一个请求头,请求头部应该至少包含传入的数据的长度
# request要求传入的请求头是一个dict格式
headers = {
# 因为使用post,至少应该包含content-length 字段
'Content-Length':len(data)
}
# 有了headers,data,url,就可以尝试发出请求了
rsp = request.urlopen(baseurl, data=data)
json_data = rsp.read().decode('utf-8')
print( type(json_data))
print(json_data)
# 把json字符串转化成字典
json_data = json.loads(json_data)
print(type(json_data))
print(json_data)
for item in json_data['data']:
print(item['k'], "--", item['v'])
- 为了更多的设置请求信息,单纯的通过urlopen函数已经不太好用了
- 需要利用request.Request 类
- 案例V6
'''
任务要求和内容跟V5 一样
本案例只是利用Request来实现v5的内容
利用parse模块模拟post请求
分析百度词典
分析步骤:
1. 打开F12
2. 尝试输入单词girl,发现每敲一个字母后都有请求
3. 请求地址是 http://fanyi.baidu.com/sug
4. 利用NetWork-All-Hearders,查看,发现FormData的值是 kw:girl
5. 检查返回内容格式,发现返回的是json格式内容==>需要用到json包
'''
from urllib import request, parse
# 负责处理json格式的模块
import json
'''
大致流程是:
1. 利用data构造内容,然后urlopen打开
2. 返回一个json格式的结果
3. 结果就应该是girl的释义
'''
baseurl = 'http://fanyi.baidu.com/sug'
# 存放用来模拟form的数据一定是dict格式
data = {
# girl是翻译输入的英文内容,应该是由用户输入,此处使用硬编码
'kw': 'girl'
}
# 需要使用parse模块对data进行编码
data = parse.urlencode(data).encode("utf-8")
# 我们需要构造一个请求头,请求头部应该至少包含传入的数据的长度
# request要求传入的请求头是一个dict格式
headers = {
# 因为使用post,至少应该包含content-length 字段
'Content-Length':len(data)
}
# 构造一个Request的实例
req = request.Request(url=baseurl, data=data, headers=headers)
# 因为已经构造了一个Request的请求实例,则所有的请求信息都可以封装在Request实例中
rsp = request.urlopen(req)
json_data = rsp.read().decode('utf-8')
print( type(json_data))
print(json_data)
# 把json字符串转化成字典
json_data = json.loads(json_data)
print(type(json_data))
print(json_data)
for item in json_data['data']:
print(item['k'], "--", item['v'])
- urllib.error
- URLError产生的原因:
- 没网
- 服务器链接失败
- 知不道制定服务器
- 是OSError的子类
- 案例V7
'''\
URLError的使用
'''
from urllib import request, error
if __name__ == '__main__':
url = "http://www.baiiiiiiiiiidu.com"
try:
req = request.Request(url)
rsp = request.urlopen( req )
html = rsp.read().decode()
print(html)
except error.URLError as e:
print("URLError: {0}".format(e.reason))
print("URLError: {0}".format(e))
except Exception as e:
print(e)
- HTTPError, 是URLError的一个子类
- 案例v8
'''\
URLError的使用
'''
from urllib import request, error
if __name__ == '__main__':
url = "http:iiiiiiiiidu//www.baidu.com/welcome.html"
url = "http://www.sipo.gov.cn/www"
try:
req = request.Request(url)
rsp = request.urlopen( req )
html = rsp.read().decode()
print(html)
except error.HTTPError as e:
print("HTTPError: {0}".format(e.reason))
print("HTTPError: {0}".format(e))
except error.URLError as e:
print("URLError: {0}".format(e.reason))
print("URLError: {0}".format(e))
except Exception as e:
print(e)
- 两者区别:
- HTTPError是对应的HTTP请求的返回码错误, 如果返回错误码是400以上的,则引发HTTPError
- URLError对应的一般是网络出现问题,包括url问题
- 关系区别: OSError-URLError-HTTPError
- UserAgent
- UserAgent: 用户代理,简称UA, 属于heads的一部分,服务器通过UA来判断访问者身份
- 常见的UA值,使用的时候可以直接复制粘贴,也可以用浏览器访问的时候抓包
1.Android
Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19
Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
2.Firefox
Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0
3.Google Chrome
Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19
4.iOS
Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
Mozilla/5.0 (iPod; U; CPU like Mac OS X; en) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/3A101a Safari/419.3
- 设置UA可以通过两种方式:
- heads
- add_header
- 案例v9
'''
访问一个网址
更改自己的UserAgent进行伪装
'''
from urllib import request, error
if __name__ == '__main__':
url = "http://www.baidu.com"
try:
# 使用head方法伪装UA
# headers = {}
# headers['User-Agent'] = 'Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3'
# req = request.Request( url, headers=headers)
# 使用add_header方法
req = request.Request(url)
req.add_header("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36")
# 正常访问
rsp = request.urlopen( req )
html = rsp.read().decode()
print(html)
except error.HTTPError as e:
print(e)
except error.URLError as e:
print(e)
except Exception as e:
print(e)
print("DONE>.............")
- ProxyHandler处理(代理服务器)
- 使用代理IP,是爬虫的常用手段
- 获取代理服务器的地址:
- www.xicidaili.com
- www.goubanjia.com
- 代理用来隐藏真实访问中,代理也不允许频繁访问某一个固定网站,所以,代理一定要很多很多
- 基本使用步骤:
1. 设置代理地址
2. 创建ProxyHandler
3. 创建Opener
4. 安装Opener
- 案例v10
'''
使用代理访问百度网站
'''
from urllib import request, error
if __name__ == '__main__':
url = "http://www.baidu.com"
# 使用代理步骤
# 1. 设置代理地址
proxy = {'http': '120.194.18.90:81' }
# 2. 创建ProxyHandler
proxy_handler = request.ProxyHandler(proxy)
# 3. 创建Opener
opener = request.build_opener(proxy_handler)
# 4. 安装Opener
request.install_opener( opener)
# 现在如果访问url,则使用代理服务器
try:
rsp = request.urlopen(url)
html = rsp.read().decode()
print(html)
except error.URLError as e:
print(e)
except Exception as e:
print(e)
- cookie & session
- 由于http协议的无记忆性,人们为了弥补这个缺憾,所采用的一个补充协议
- cookie是发放给用户(即http浏览器)的一段信息,session是保存在服务器上的对应的另一半信息,用来记录用户信息
- cookie和session的区别
- 存放位置不同
- cookie不安全
- session会保存在服务器上一定时间,会过期
- 单个cookie保存数据不超过4k, 很多浏览器限制一个站点最多保存20个
- session的存放位置
- 存在服务器端
- 一般情况,session是放在内存中或者数据库中
- 没有cookie登录 案例v11,可以看到,没使用cookie则反馈网页为未登录状态
from urllib import request
if __name__ == '__main__':
url = "http://www.renren.com/965187997/profile"
rsp = request.urlopen(url)
html = rsp.read().decode()
with open("rsp.html", "w") as f:
f.write(html)
- 使用cookie登录
- 直接把cookie复制下来,然后手动放入请求头, 案例 v12
from urllib import request
if __name__ == '__main__':
url = "http://www.renren.com/965187997/profile"
headers = {
"Cookie": "anonymid=jfosp2p2-48i1hh; depovince=BJ; _r01_=1; jebe_key=f2e12094-303b-4171-900f-ed304e5a5ba1%7C7629e5c8e0f7f334244eb5436ef05a2c%7C1523070488659%7C1%7C1523070515670; wp_fold=0; jebecookies=a201c15f-9745-40fc-9d32-7112f8cf849f|||||; ick_login=cbfe66e0-743c-46a4-a956-7d692056361d; _de=420A8DC764CD1624FC7C8526DA9A3A25; p=db36f5ff987e7e58c901f6194a22b7007; first_login_flag=1; ln_uact=13119144223; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=1b2976196819d4a57127f5b87ac495f77; societyguester=1b2976196819d4a57127f5b87ac495f77; id=965187997; xnsid=61e9001d; __utma=151146938.742687335.1523070758.1523070758.1523070758.1; __utmc=151146938; __utmz=151146938.1523070758.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmt=1; __utmb=151146938.1.10.1523070758; ver=7.0; loginfrom=null; JSESSIONID=abcIxsy_d_tR06bwXfEkw; _urm_965187997=21"
}
req = request.Request(url, headers=headers)
rsp = request.urlopen(req)
html = rsp.read().decode()
with open("rsp.html", "w") as f:
f.write(html)
- http模块包含一些关于cookie的模块,通过他们我们可以自动使用cookie
- CookieJar
- 管理存储cookie,向传出的http请求添加cookie,
- cookie存储在内存中,CookieJar实例回收后cookie将消失
- FileCookieJar(filename, delayload=None, policy=None):
- 使用文件管理cookie
- filename是保存cookie的文件
- MozillaCookieJar(filename, delayload=None, policy=None):
- 创建与mocilla浏览器cookie.txt兼容的FileCookieJar实例
- LwpCookieJar(filename, delayload=None, policy=None):
- 创建与libwww-perl标准兼容的Set-Cookie3格式的FileCookieJar实例
- 他们的关系是: CookieJar-->FileCookieJar-->MozillaCookieJar & LwpCookieJar
- 利用cookiejar访问人人, 案例13
from urllib import request, parse
from http import cookiejar
# 创建cookiejar的实例
cookie = cookiejar.CookieJar()
# 生成 cookie的管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 创建http请求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
# 创建请求管理器
opener = request.build_opener(http_handler, https_handler, cookie_handler)
def login():
'''
负责初次登录
需要输入用户名密码,用来获取登录cookie凭证
:return:
'''
# 此url需要从登录form的action属性中提取
url = "http://www.renren.com/PLogin.do"
# 此键值需要从登录form的两个对应input中提取name属性
data = {
"email": "13119144223",
"password": "123456"
}
# 把数据进行编码
data = parse.urlencode(data)
# 创建一个请求对象
req = request.Request(url, data=data.encode())
# 使用opener发起请求
rsp = opener.open(req)
def getHomePage():
url = "http://www.renren.com/965187997/profile"
# 如果已经执行了login函数,则opener自动已经包含相应的cookie值
rsp = opener.open(url)
html = rsp.read().decode()
with open("rsp.html", "w") as f:
f.write(html)
if __name__ == '__main__':
login()
getHomePage()
- 自动使用cookie登录,大致流程是
- 打开登录页面后自动通过用户名密码登录
- 自动提取反馈回来的cookie
- 利用提取的cookie登录隐私页面
- handler是Handler的实例,常用参看案例代码
- 用来处理复杂请求
# 生成 cookie的管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 创建http请求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
- 创立handler后,使用opener打开,打开后相应的业务由相应的hanlder处理
- cookie作为一个变量,打印出来, 案例 v14
from urllib import request, parse
from http import cookiejar
# 创建cookiejar的实例
cookie = cookiejar.CookieJar()
# 生成 cookie的管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 创建http请求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
# 创建请求管理器
opener = request.build_opener(http_handler, https_handler, cookie_handler)
def login():
'''
负责初次登录
需要输入用户名密码,用来获取登录cookie凭证
:return:
'''
# 此url需要从登录form的action属性中提取
url = "http://www.renren.com/PLogin.do"
# 此键值需要从登录form的两个对应input中提取name属性
data = {
"email": "13119144223",
"password": "123456"
}
# 把数据进行编码
data = parse.urlencode(data)
# 创建一个请求对象
req = request.Request(url, data=data.encode())
# 使用opener发起请求
rsp = opener.open(req)
if __name__ == '__main__':
'''
执行完login之后,会得到授权之后的cookie
我们尝试把cookie打印出来
'''
login()
print(cookie)
for item in cookie:
print(type(item))
print(item)
for i in dir(item):
print(i)
- cookie的属性
- name: 名称
- value: 值
- domain:可以访问此cookie的域名
- path: 可以发昂文此cookie的页面路径
- expires:过期时间
- size: 大小
- Http字段
- cookie的保存-FileCookieJar, 案例v15
from urllib import request, parse
from http import cookiejar
# 创建filecookiejar的实例
filename = "cookie.txt"
cookie = cookiejar.MozillaCookieJar(filename)
# 生成 cookie的管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 创建http请求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
# 创建请求管理器
opener = request.build_opener(http_handler, https_handler, cookie_handler)
def login():
'''
负责初次登录
需要输入用户名密码,用来获取登录cookie凭证
:return:
'''
# 此url需要从登录form的action属性中提取
url = "http://www.renren.com/PLogin.do"
# 此键值需要从登录form的两个对应input中提取name属性
data = {
"email": "13119144223",
"password": "123456"
}
# 把数据进行编码
data = parse.urlencode(data)
# 创建一个请求对象
req = request.Request(url, data=data.encode())
# 使用opener发起请求
rsp = opener.open(req)
# 保存cookie到文件
# ignor_discard表示及时cookie将要被丢弃也要保存下来
# ignore_expire表示如果该文件中cookie即使已经过期,保存
cookie.save(ignore_discard=True, ignore_expires=True)
if __name__ == '__main__':
login()
- cookie的读取, 案例v16
from urllib import request, parse
from http import cookiejar
# 创建cookiejar的实例
cookie = cookiejar.MozillaCookieJar()
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
# 生成 cookie的管理器
cookie_handler = request.HTTPCookieProcessor(cookie)
# 创建http请求管理器
http_handler = request.HTTPHandler()
# 生成https管理器
https_handler = request.HTTPSHandler()
# 创建请求管理器
opener = request.build_opener(http_handler, https_handler, cookie_handler)
def getHomePage():
url = "http://www.renren.com/965187997/profile"
# 如果已经执行了login函数,则opener自动已经包含相应的cookie值
rsp = opener.open(url)
html = rsp.read().decode()
with open("rsp.html", "w") as f:
f.write(html)
if __name__ == '__main__':
getHomePage()
- SSL
- SSL证书就是指遵守SSL安全套阶层协议的服务器数字证书(SercureSocketLayer)
- 美国网景公司开发
- CA(CertifacateAuthority)是数字证书认证中心,是发放,管理,废除数字证书的收信人的第三方机构
- 遇到不信任的SSL证书,需要单独处理,案例v17
from urllib import request
# 导入pythopn ssl处理模块
import ssl
# 利用非认证上下文环境替换认证的向下文环境
ssl._create_default_https_context = ssl._create_unverified_context
url = "https://www.12306.cn/mormhweb/"
rsp = request.urlopen(url)
html = rsp.read().decode()
print(html)
- js加密
- 有的反爬虫策略采用js对需要传输的数据进行加密处理(通常是取md5值)
- 经过加密,传输的就是密文,但是
- 加密函数或者过程一定是在浏览器完成,也就是一定会把代码(js代码)暴露给使用者
- 通过阅读加密算法,就可以模拟出加密过程,从而达到破解
- 过程参看案例v18,
'''
破解有道词典
V1
'''
from urllib import request, parse
def youdao(key):
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
data = {
"i": "boy",
"from":"AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": "1523100789519",
"sign": "b8a55a436686cd89873fa46514ccedbe",
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action":"FY_BY_REALTIME",
"typoResult": "false"
}
# 参数data需要是bytes格式
data = parse.urlencode(data).encode()
headers = {
"Accept": "application/json,text/javascript,*/*;q=0.01",
#"Accept-Encoding": "gzip,deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Content-Length": "200",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"Cookie": "OUTFOX_SEARCH_USER_ID=-1548144101@10.168.8.76;JSESSIONID=aaaTLWzfvp5Hfg9mAhFkw;OUTFOX_SEARCH_USER_ID_NCOO=1999296830.4784973;___rl__test__cookies=1523100789517",
"Host": "fanyi.youdao.com",
"Origin": "http://fanyi.youdao.com",
"Referer": "http://fanyi.youdao.com/",
"User-Agent": "Mozilla/5.0( X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36 X-Requested-With: XMLHttpRequest"
}
req = request.Request(url=url, data=data, headers=headers)
rsp = request.urlopen(req)
html = rsp.read().decode()
print(html)
if __name__ == '__main__':
youdao("boy")
v19
- 过程比较啰嗦,笔记比较少,仔细观察
'''
V2
处理js加密代码
'''
'''
通过查找,能找到js代码中操作代码
1. 这个是计算salt的公式 r = "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10));
2. sign: n.md5("fanyideskweb" + t + r + "ebSeFb%=XZ%T[KZ)c(sy!");
md5一共需要四个参数,第一个和第四个都是固定值的字符串,第三个是所谓的salt,第二个是。。。。。
第二个参数就是输入的要查找的单词
'''
def getSalt():
'''
salt公式是: "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10));
把他翻译成python代码
:return:
'''
import time, random
salt = int(time.time()*1000) + random.randint(0,10)
return salt
def getMD5(v):
import hashlib
md5 = hashlib.md5()
# update需要一共bytes格式的参数
md5.update(v.encode("utf-8"))
sign = md5.hexdigest()
return sign
def getSign(key, salt):
sign = 'fanyideskweb'+ key + str(salt) + "ebSeFb%=XZ%T[KZ)c(sy!"
sign = getMD5(sign)
return sign
from urllib import request, parse
def youdao(key):
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
salt = getSalt()
data = {
"i": key,
"from":"AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": str(salt) ,
"sign": getSign(key, salt),
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action":"FY_BY_REALTIME",
"typoResult": "false"
}
print(data)
# 参数data需要是bytes格式
data = parse.urlencode(data).encode()
headers = {
"Accept": "application/json,text/javascript,*/*;q=0.01",
#"Accept-Encoding": "gzip,deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Content-Length": len(data),
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"Cookie": "OUTFOX_SEARCH_USER_ID=-1548144101@10.168.8.76;JSESSIONID=aaaTLWzfvp5Hfg9mAhFkw;OUTFOX_SEARCH_USER_ID_NCOO=1999296830.4784973;___rl__test__cookies=1523100789517",
"Host": "fanyi.youdao.com",
"Origin": "http://fanyi.youdao.com",
"Referer": "http://fanyi.youdao.com/",
"User-Agent": "Mozilla/5.0( X11; Linux x86_64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36 X-Requested-With: XMLHttpRequest"
}
req = request.Request(url=url, data=data, headers=headers)
rsp = request.urlopen(req)
html = rsp.read().decode()
print(html)
if __name__ == '__main__':
youdao("boy")
- ajax
- 异步请求
- 一定会有url,请求方法,可能有数据
- 一般使用json格式
- 案例,爬去豆瓣电影, 案例v20
'''
爬去豆瓣电影数据
了解ajax的基本爬去方式
'''
from urllib import request
import json
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=40&limit=20"
rsp = request.urlopen(url)
data = rsp.read().decode()
data = json.loads(data)
print(data)
# Requests-献给人类
- HTTP for Humans,更简洁更友好
- 继承了urllib的所有特征
- 底层使用的是urllib3
- 开源地址: https://github.com/requests/requests
- 中文文档: http://docs.python-requests.org/zh_CN/latest/index.html
- 安装: conda install requests
- get请求
- requests.get(url)
- requests.request("get", url)
- 可以带有headers和parmas参数
- 案例v21
import requests
url = "http://www.baidu.com"
# 两种请求方式
# 使用get请求
rsp = requests.get(url)
print(rsp.text)
# 使用request请求
rsp = requests.request("get", url)
print(rsp.text)
- get返回内容
- 案例v22
'''
使用参数headers和params
研究返回结果
'''
import requests
# 完整访问url是下面url加上参数构成
url = "http://www.baidu.com/s?"
kw = {
"wd": "王八蛋"
}
headers = {
"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36"
}
rsp = requests.get(url, params=kw, headers=headers )
print(rsp.text)
print(rsp.content)
print(rsp.url)
print(rsp.encoding)
print(rsp.status_code) # 请求返回码
- post
- rsp = requests.post(url, data=data)
- 参看案例23
'''
python中正则模块是re
使用大致步骤:
1. compile函数讲正则表达式的字符串便以为一个Pattern对象
2. 通过Pattern对象的一些列方法对文本进行匹配,匹配结果是一个Match对象
3. 用Match对象的方法,对结果进行操纵
'''
import re
# \d表示以数字
# 后面+号表示这个数字可以出现一次或者多次
s = r"\d+" # r表示后面是原生字符串,后面不需要转义
# 返回Pattern对象
pattern = re.compile(s)
# 返回一个Match对象
# 默认找到一个匹配就返回
m = pattern.match("one12two2three3")
print(type(m))
# 默认匹配从头部开始,所以此次结果为None
print(m)
# 返回一个Match对象
# 后面为位置参数含义是从哪个位置开始查找,找到哪个位置结束
m = pattern.match("one12two2three3", 3, 10)
print(type(m))
# 默认匹配从头部开始,所以此次结果为None
print(m)
print(m.group())
print(m.start(0))
print(m.end(0))
print(m.span(0))
- date, headers要求dict类型
- proxy
-
proxies = {
"http":"address of proxy",
"https": "address of proxy"
}
rsp = requests.request("get", "http:xxxxxx", proxies=proxies)
- 代理有可能报错,如果使用人数多,考虑安全问题,可能会被强行关闭
- 用户验证
- 代理验证
#可能需要使用HTTP basic Auth, 可以这样
# 格式为 用户名:密码@代理地址:端口地址
proxy = { "http": "china:123456@192.168.1.123:4444"}
rsp = requests.get("http://baidu.com", proxies=proxy)
- web客户端验证
- 如果遇到web客户端验证,需要添加auth=(用户名,密码)
autu=("test1", "123456")#授权信息
rsp = requests.get("http://www.baidu.com", auth=auth)
- cookie
- requests可以自动处理cookie信息
rsp = requests.get("http://xxxxxxxxxxx")
# 如果对方服务器给传送过来cookie信息,则可以通过反馈的cookie属性得到
# 返回一个cookiejar实例
cookiejar = rsp.cookies
#可以讲cookiejar转换成字典
cookiedict = requests.utils.dict_from_cookiejar(cookiejar)
- session
- 跟服务器端session不是一个东东
- 模拟一次会话,从客户端浏览器链接服务器开始,到客户端浏览器断开
- 能让我们跨请求时保持某些参数,比如在同一个session实例发出的 所有请求之间保持cookie
# 创建session对象,可以保持cookie值
ss = requests.session()
headers = {"User-Agetn":"xxxxxxxxxxxxxxxxxx"}
data = {"name":"xxxxxxxxxxx"}
# 此时,由创建的session管理请求,负责发出请求,
ss.post("http://www.baidu.com", data=data, headers=headers)
rsp = ss.get("xxxxxxxxxxxx")
- https请求验证ssl证书
- 参数verify负责表示是否需要验证ssL证书,默认是True
- 如果不需要验证ssl证书,则设置成False表示关闭
rsp = requests.get("https://www.baidu.com", verify=False)
# 如果用verify=True访问12306,会报错,因为他证书有问题