yython爬虫基础知识入门
Python爬虫
关注公众号“轻松学编程”了解更多。
大纲:
1、获取响应
urllib(python3)/urllib2-urllib(python2)
requests(urllib3) --get/post
2、解析响应
HTML、json
re/bs4/xpath(描述性语句)
3、通用动态数据加载 selenium(自动化测试框架) + phantomJS(无界面浏览器)、handles
4、scrapy框架
高性能(多线程-10条、并发-16的框架)、高定制(爬虫)
提供了数据的下载、解析(xpath)、持久化
5、scrapy-redis(分布式策略)
核心–redis-组件(一主多从) —在redis实现任务分配、指纹去重
根本–scrapy
6、解决的问题
反反爬虫(爬虫工程师)
反爬虫(对web后端–Django中间件)
一、urllib2库的基本使用
所谓网页抓取,就是把URL地址中指定的网络资源从网络流中读取出来,保存到本地。 在Python中有很多库可以用来抓取网页,我们先学习urllib2。
urllib2 是 Python2.7 自带的模块(不需要下载,导入即可使用)
urllib2 官方文档:https://docs.python.org/2/library/urllib2.html
urllib2 源码:https://hg.python.org/cpython/file/2.7/Lib/urllib2.py
urllib2 在 python3.x 中被改为urllib.request
import urllib2
import urllib
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
def baiduAPI(wd):
'''
百度接口
:return:response
'''
# url编码,多个参数,按字典格式写,自动拼接&
wd = urllib.urlencode({"wd": wd, "rsv_spt": "1"})
url = 'https://www.baidu.com/s?' + wd
print url
request = urllib2.Request(url, headers=headers)
respose = urllib2.urlopen(request)
return respose.read()
if __name__ == '__main__':
kw = raw_input("请输入搜索关键字:")
response = baiduAPI(kw)
print response
二、urllib
1、简介
官方文档地址:https://docs.python.org/3/library/urllib.html
Urllib是python内置的HTTP请求库,提供了一系列用于操作URL的功能。
包括以下模块 :
urllib.request 请求模块
urllib.error 异常处理模块
urllib.parse url解析模块
urllib.robotparser robots.txt解析模块
urllib的request
模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应。
2、urlopen
######2.1 参数介绍:
urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
*, cafile=None, capath=None,
cadefault=False, context=None):
常用参数有3个:
url:请求体(包含请求地址、代理等信息);
data:如果添加data参数就是以post请求方式请求,如果没有data参数就是get请求方式 ;
timeout:请求时间
######2.2 返回值:
# 向指定的url发送请求,返回一个类文件对象,支持python文件操作
read() #全部读取
readlines() #以行方式全部读取
readline() #读取一行
2.3 例子
获取get请求
import urllib.request
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
}
'''
url, data=None, 获取get请求
headers={} 请求头
'''
req = urllib.request.Request('https://www.baidu.com', headers=header) # 请求体
print(req.get_header('User-agent')) # 第一个必须大写,其余必须小写
response = urllib.request.urlopen(req) # 发送请求
print(response.read().decode())
获取post请求:
post请求一般用于Form表单,可以封装成一个字典,放在urllib.request.Request()中,返回一个请求体。
从浏览器中获取一个form-data数据
把复制的数据放到sublime编辑器中,使用正则表达式替换为json格式:
查找->替换
正则表达式为:
^(.*):(.*)$
"\1":"\2",
import urllib
import json
from urllib import request, parse
#请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
def getJobTotalPage(kw):
'''
获取相关岗位总页数
:param kw: 岗位名
:return: 总页数
'''
# 种子
url = "https://job.alibaba.com/zhaopin/socialPositionList/doList.json"
# 表单数据
data = {
"pageSize": "10",
"t": "0.24795042432579706",
"keyWord": kw,
"location": "",
"second": "",
"first": "",
"pageIndex": "1"
}
# url编码
data = urllib.parse.urlencode(data).encode('utf-8')
# 请求,data=data表明是POST请求
req = urllib.request.Request(url, data=data, headers=headers)
# 获取响应
response = urllib.request.urlopen(req).read().decode('utf-8')
# 转json
data = json.loads(response)
# 获取岗位数量
totlPage = data['returnValue']['totalPage']
return int(totlPage)
def getJobInfo(kw, pagenum):
'''
获取岗位数量
:param kw: 搜索关键字
:param pagenum: 总页面数量
:return: 岗位信息
'''
url = "https://job.alibaba.com/zhaopin/socialPositionList/doList.json"
# 根据岗位类型抓取全部页面数据
for i in range(1, pagenum + 1):
data = {
"pageSize": "10",
"t": "0.24795042432579706",
"keyWord": kw,
"location": "",
"second": "",
"first": "",
"pageIndex": i
}
# url编码
data = urllib.parse.urlencode(data).encode('utf-8') # POST data should be bytes
'''
url, data=None, headers={}
'''
req = urllib.request.Request(url, data=data, headers=headers) # POST请求
response = urllib.request.urlopen(req).read().decode('utf-8')
# print(response)
# 转json
data = json.loads(response)
# 获取job列表
jobList = data['returnValue']['datas']
# print(jobList)
# 提取岗位详细信息
for job in jobList:
# 学历
degree = job['degree']
# 部门
departmentName = job['departmentName']
# 描述
description = job['description'].replace('<br/>', '')
# 技术分类
firstCategory = job['firstCategory']
# 岗位名
name = job['name']
# 要求
requirement = job['requirement'].replace('<br/>', '')
print(degree, departmentName, description, requirement)
if __name__ == '__main__':
# 岗位列表
jobList = ['python', 'java']
for job in jobList:
totlPage = getJobTotalPage(job)
print(totlPage)
getJobInfo(job, totlPage)
3、User-Agent
######3.1 简介
有一些网站不喜欢被爬虫程序访问,所以会检测连接对象,如果是爬虫程序,也就是非人点击访问,它就会不让你继续访问,所以为了要让程序可以正常运行,需要隐藏自己的爬虫程序的身份。此时,我们就可以通过设置User Agent的来达到隐藏身份的目的,User Agent的中文名为用户代理,简称UA。
User Agent存放于Headers中,服务器就是通过查看Headers中的User Agent来判断是谁在访问。在Python中,如果不设置User Agent,程序将使用默认的参数,那么这个User Agent就会有Python的字样,如果服务器检查User Agent,那么没有设置User Agent的Python程序将无法正常访问网站。
######3.2 常用消息头(详解http请求消息头)
- Accept:text/html,image/*(告诉服务器,浏览器可以接受文本,网页图片)
- Accept-Charaset:ISO-8859-1 [接受字符编码:iso-8859-1]
- Accept-Encoding:gzip,compress[可以接受 gzip,compress压缩后数据]
- Accept-Language:zh-cn[浏览器支持的语言]
- Host:localhost:8080[浏览器要找的主机]
- Referer:http://localhost:8080/test/abc.html[告诉服务器我来自哪里,常用于防止下载,盗链]
- User-Agent:Mozilla/4.0(Com…)[告诉服务器我的浏览器内核]
- Cookie:[会话]
- Connection:close/Keep-Alive [保持链接,发完数据后,我不关闭链接]
- Date:[浏览器发送数据的请求时间]
header = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"}
request = urllib2.Request(url, headers=header) # 构造一个请求对象发送请求,伪装浏览器访问
######3.3 添加更多的Header信息
在 HTTP Request 中加入特定的 Header,来构造一个完整的HTTP请求消息。
可以通过调用Request.add_header() 添加/修改一个特定的header 也可以通过调用Request.get_header()来查看已有的header。
添加一个特定的header
request.add_header("Connection", "keep-alive") # 保持连接
print request.get_full_url() # 访问的网页链接
print request.get_host() # 服务器域名
print request.get_method() # get或post
print request.get_type() # http/https/ftp
response = urllib2.urlopen(request)
print response.code # 状态码200, 404,500
print response.info # 网页详细信息
data = response.read().decode("gbk")
print response.code # 响应状态码
return data
我们都知道Http协议中参数的传输是"key=value"这种简直对形式的,如果要传多个参数就需要用“&”符号对键值对进行分割。如"?name1=value1&name2=value2",这样在服务端在收到这种字符串的时候,会用“&”分割出每一个参数,然后再用“=”来分割出参数值。
4、编码与解码
编码工作使用urllib的urlencode()函数,帮我们将key:value这样的键值对转换成"key=value"这样的字符串,解码工作可以使用urllib的unquote()函数。(注意,不是urllib2.urlencode())
urllib.urlencode(keyWord) # url编码
urllib.unquote(kw) # 解码
5、抓取ajax数据
import urllib.request
import json
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
# ajax请求url
for i in range(100):
url = "https://movie.douban.com/j/new_search_subjects?sort=T&range=0,10&tags=&start=%d" % (i * 20)
req = urllib.request.Request(url, headers=headers)
response = urllib.request.urlopen(req).read().decode('utf-8')
# print(response)
# json数据
data = json.loads(response)
for i in data['data']:
# 明星
casts = i['casts']
# 导演
directors = i['directors']
print(casts, directors)
# 写入文件
with open('movie.txt', 'a+', encoding='utf-8', errors='ignore') as f:
f.write(str((casts, directors)) + '\n')
f.flush()
6、处理HTTPS请求 SSL证书验证
现在随处可见 https 开头的网站,urllib2可以为 HTTPS 请求验证SSL证书,就像web浏览器一样,如果网站的SSL证书是经过CA认证的,则能够正常访问,如:https://www.baidu.com/等…
如果SSL证书验证不通过,或者操作系统不信任服务器的安全证书,比如浏览器在访问12306网站如:https://www.12306.cn/mormhweb/的时候,会警告用户证书不受信任。(据说 12306 网站证书是自己做的,没有通过CA认证)。
import urllib
from urllib import request
import ssl
context = ssl._create_unverified_context() # 忽然安全证书
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}
url = "https://www.12306.cn/mormhweb/"
req = urllib.request.Request(url, headers=headers)
# 忽略证书安全ssl
response = urllib.request.urlopen(req, context=context)
print(response.read().decode())
后记
【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。
也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!
公众号
关注我,我们一起成长~~