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】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!

公众号

公众号

赞赏码

关注我,我们一起成长~~

posted @ 2018-07-02 20:01  轻松学编程  阅读(93)  评论(0编辑  收藏  举报