8月13号开始,用了六天学习了来自传智播客的“六节课掌握爬虫入门”课程,对python爬虫技术有了初步的了解,能够用爬虫的原理写基本的小程序,通过对样例对人人网、豆瓣电影以及糗事百科的爬取,了解了html,xpath等知识。写下总结,以防忘记。

第一课:爬虫基础知识和软件准备

什么是爬虫:

  • 爬虫就是指模拟客户端(浏览器)发送网络请求获取响应,按规则提取数据的程序
  • 模拟客户端(浏览器)发送网络请求:和浏览器发送一模一样的数据

爬虫获取的数据去了哪里:

  • 1.可以通过处理或者直接呈现出来,获取我们想要的数据;
  • 2.可以进一步分析,机器学习领域等。

需要的软件和环境:

  • python版本:python3.6.5(3.x即可)
  • python IDE:我选择的是pycharm,当然也可以用VS code,甚至有些大神会选择用python自带的IDLE,顺手就好。
  • 浏览器:我选的是我常用的一款浏览器Google的Chrome浏览器,功能比较强大,扩展性能好。选择自己顺手的就好,不必苛求,当然,不建议用IE和某些不知名的浏览器,会出各种奇奇怪怪的东西,国产浏览器的话,360,QQ还是不错的。
  • 需要导入的包:requests(获取响应),json(获取网页内容,Python自带),lxml(写xpath,获取网页内容),retrying(提高容错性)
  • 前期准备:要了解python的基本语法,熟悉列表,字典,函数(函数的创建和调用),以及自定义类的用法,需要一部分html的知识。

浏览器的请求

  • URL(统一资源定位符):
  • 在chrome浏览器中“右键”→“检查”点击选项卡“network”
  • URL = 请求的协议(http/https)+网站域名+资源的路径+url地址参数(对方服务器解析)
  • URL地址中如果出现百分号,乱码等,可以用相关工具进行解码。
  • 浏览器请求URL地址:
  • 当前URL的响应+js+css+图片–>elements中的内容
  • 爬虫请求URL地址:
  • 仅包含当前URL的响应
  • elements的内容和爬虫获取到的URL地址的响应不同:
  • 所以需要爬虫以当前对应的URL地址的响应为准提取数据
  • 当前URL地址的响应,在network里Response里可以查看,也可以打开网页原码进行查看

以上两个的区别,比如我们请求一个JS文件的URL,大家都知道,js文件是用来规范网页显示格式的一种程序,如果我们用浏览器请求,那我们可以看到它正常的显示效果,但当我们用爬虫去请求时,只会拿到一堆字符串,无法执行。

第二课:认识HTTP、HTTPS和requests模块

认识HTTP、HTTPS

  • HTTP:超文本传输协议
  • 以明文形式传输,效率高,不安全
  • HTTPS:HTTP+SSL(安全套接字层)
  • 传输数据前先加密,接收数据后解密获取内容,效率低,更安全。
  • GET请求和POST请求的区别:
  • GET请求无请求体,POST请求有请求体。
  • POST请求常用于登录、注册,传输大文本等(因为POST请求可以携带比GET更大的数据量),例如翻译网页等。
  • HTTP协议之请求
  • 1.请求行
  • 2.请求头
  • User-Agent(用户代理):对方服务器通过user-agent知道请求对方资源的是什么浏览器,或者说是不是浏览器,通过chrome可以模仿(模拟)手机版的网页浏览,模仿时候,user-agent是改成手机版的。
  • Accept:告诉服务端,我想接受什么数据
  • Accept-Encoding:告诉服务端我可以接受什么编码方式的数据。
  • Accept-Language:告诉服务端我们希望接受什么语言的数据。
  • Cookie:用来存储用户信息的,每次请求都会被带上发送给对方的浏览器。
  • 要获取登陆后才能访问的页面的内容
  • 对方的服务器会通过cookie来判断爬虫

我们已经了解过了,爬虫就是用来模拟浏览器发送请求,怎样才能模拟的像呢?我们可以看一下浏览器里面的Request Header 发现里面有许多参数,上面罗列的这几项也包含在这里面,所以,如果想要模拟的像,就可以把这些参数全部带上。特别是,当我们发现只带User-Agent不行时,就需要带上一些别的字段,如host等。

  • 3.请求体:携带数据
  • GET请求:没有请求体
  • POST请求:有请求体
  • HTTP协议之响应:
  • 1.响应头
  • Set-Cookie:通过这个键,对方服务器可以向本地设置Cookie(Response Cookie)
  • 2.响应体
  • URL地址对应的响应

requests模块

  • 安装requests模块:
  • requests模块是一个第三方模块
  • pip install requests
  • 或者在你的IDE中直接加载配置(建议)
  • requests模块的使用
  • 首先,像许多别的python第三方模块一样,用之前,我们需要
import request
  • 发送GET、POST请求,获取响应
response1 = requests.get(url)   #get请求,获取响应
response2 = requests.post(url,data = {请求体的字典})    #post请求,需要请求体
response的方法:
  • 1.response.content.decode()

此方法是把响应的二进制字节流转化为字符串类型

  • 2.response.text

该方法获取网页内容时往往会出现乱码,所以要在此前加上一个response.encoding = “utf-8”

  • 3.response.request.url

获取发送请求的url地址

  • 4.response.url

获取响应的url地址

  • 5.response.request.headers

请求头

  • 6.response.headers

响应头

获取网页原码的方式:
  • 1.response.content.decode()
  • 2.response.content.decode(“gbk”)

某些网站的 编码方式不是使用的"utf-8"而是"gbk"

  • 3.response.text 》

因为.text方法是根据响应头部的编码进行推测,所以放到最后使用,有时候也会推测正确

当我们拿到一个网页,用以上三种方式,一定可以获取到网页正确解码方式的字符串

携带header的请求
  • 为了模拟浏览器(更像)获得和浏览器一模一样的内容。
headers = {
"User-Agent","Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1"
,"Referer":"https://www.baidu.com/link?url=2AZ4aoeuSBsv_DIT2glxe8YKtzrFnpjE6gE0kBfZAIYHR68fCE_qEqJHAwCGLxwZ9EgAWJ1VlgWpsc2AP0w9h8HCCYyk76C4ZkZ31Kkx6Oa&wd=&eqid=b52b5e950002d7ea000000045b7ab019"
,"Cookie":"__cfduid=d1980ca26bf900a830b821bbeb347e14e1524844627; BDUSS=ZZTlpUbjFKSWlzNWd3MFBJTnA2OXRTfjVRM2JtQjExVlNxbXVwRmFuOWhRcGRiQVFBQUFBJCQAAAAAAAAAAAEAAADfpd0Tz8q9o8bvz7rXqgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGG1b1thtW9bbF; BIDUPSID=64317FC091E534AA95A51E108E720B05; PSTM=1534572862; BAIDUID=64317FC091E534AA9D2CA222BE99583F:FG=1; PSINO=5; pgv_pvi=8543101952; pgv_si=s5921124352; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; H_PS_PSSID=1441_21124_26350_26921_20929; Hm_lvt_55b574651fcae74b0a9f1cf9c8d7c93a=1534689869,1534750696,1534750859,1534767134; Hm_lpvt_55b574651fcae74b0a9f1cf9c8d7c93a=1534767134; BKWPF=3"
,"Host":"baike.baidu.com"
}

当我们只带header不够的时候,可以带点别的东西进去,比如Referer,Host,还有最重要的Cookie

例子是百度百科“HTTP状态码”词条,代理用的是IPad

注意,这些全部都是放在header里面的,当现实状态码为200时,但没有反应,就是缺Header

第三课:retrying模块的使用和携带cookie的请求

超时参数的使用
  • requests.get(url,headers = headers, timeout = 3)#timeout 就是我们所说的超时参数,设置为3,是指3秒如果还链接不到(没有返回响应)的话,就报错。
retrying模块的使用
  • retrying模块是一个第三方模块,我们在此使用这个模块的目的是防止网站请求超时
  • 举个例子

假设我们要获取一批url地址,其中某一个地址处于某种原因,链接失败,当我一般碰到链接失败的时候,一般会选择刷新网页,但如果我们发现刷新几次都没有反应,我们就不必在这个地方纠结,直接爬取下一个网页就好了,retrying模块就是起到这个目的。

  • 首先 pip install retrying
form retrying import retry

@retry(stop_max_attempt_time = 3)
def func1():
    print("~~~~~~~~~")
    raise ValueError("error!")

上面函数用retry修饰,函数反复执行三次,如果三次全报错,则报错,如果三次中有一次正常运行,则程序继续走。“stop_max_attemp_time”参赛可以更改。

requests模块处理cookie相关请求:
  • 直接携带cookie请求url地址:
  • 直接把cookie放在requests的方法的headers参数里(抓包获取cookie)
  • cookie字典:获取cookie字典,然后放在cookie参数里
cookie = "anonymid=jktqcaaz-yc3q1e; depovince=SD; jebecookies=24118536-4dae-4958-ac10-cdf927806f0c|||||; _r01_=1; JSESSIONID=abcWx0fQyxjZQayV6K4uw; ick_login=74306d5d-341d-4ff8-8f3c-5d386dc971cd; _de=FF874E9B1254101280671A4BC2EEBA1B; p=e33464b788d6245684e63870b87557347; first_login_flag=1; ln_uact=15062181376; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; t=74d612143be059c7c0a75fd5433c1dc87; societyguester=74d612143be059c7c0a75fd5433c1dc87; id=568207047; xnsid=c76bfd9c; loginfrom=syshome; wp_fold=0"
cookie_dict = {i.split("=")[0]:i.split("=")[-1] for i in cookie.split(";")}
  • 发送post请求获取cookie
  1. session = requests.session()#session的方法和requests一样
  2. session.post(url, data, headers)#服务器设置的cookie会保存在session中
  3. session.get(url)#会带上之前保存在session中的cookie

第四课:数据提取方法之json

json

  • 数据交换格式,看起来像python类型(列表,字典)的字符串
  • 哪里会返回json的数据
  • 浏览器切换到手机版,并不是每个页面都会返回json数据
  • 抓包的软件和app
  • json.loads()
  • 把json字符串转换为python类型
  • json.loads(‘json字符串’)#如果保存,一般由于不是json字符串导致的
  • json.dumps(
  • 把python类型转化为json字符串
  • json.dumps({‘1’:“hello”,‘2’:‘world’},ensure_ascii = False, indent = 2)
  • ensure_ascii = False #能够让中文显示
  • indent = 2 #上一行和下一行直接回车空格

注意一点,当URL中带有callback=???时,直接删掉即可,没有什么用,带着还不能构造json字符串

第五课:xpath和lxml模块

xpath

  • 一门从html提取数据的语言

xpath语法

  • xpath helper插件:帮助我们从elements中定位数据
  • 1.“/”选择节点(标签):
  • ‘/html/head/meta’:能够选择html head中所有meta标签
  • 2.“//”从任意节点开始选择
  • “//li”选择页面上所有li标签
  • “/html/head//link”选择head下所有的link标签
  • 3."@"符号的用途
  • 选择具体的某个元素:“//div[@class = ‘content’]/ul/li”

选择class = ‘content’ 的div下的ul的li

  • “/a/@href”获取选择的a的href的值
  • 4.获取文本
  • /a/text():获取a的文本
  • /a//text():获取a下所有的文本
  • 5.“./a”当前节点下的a标签

lxml模块

安装lxml
  • pip install lxml
  • 在IDE中直接配置安装(推荐)
使用
from lxml import etree
elements = etree.HTML('html字符串')
elements.xpath('xpath语句')

第六课:实战训练案例/爬虫流程概念

基础知识补充

  • 列表推导式
  • 帮助我们迅速生成列表
[i for i in range(1,10)]

生成一个[1,2,3,4,5,6,7,8,9,10]列表

[i+10 for i in range(10)]

生成[10,12,13……18,19]列表

  • 字典推导式
  • 帮助我们快速生成字典
{i+10: i for i in range(10)}

生成的字典为{10:0,11:1,12:2……18:8,19:9}

  • 三元运算符
a = 10 if 3<4 else 20

a = 10 因为3<4成立

a = 10 if 3>4 else 20

a = 20 因为3>4不成立

-若if后面条件成立,则把if前面的值赋给变量,若不成立,则把后面的值付给变量。

一个爬虫的基本流程(讨论)
  • 1.URL:
  • 知道URL地址的规律和需要爬取的数量,构造URL地址列表,可以用python字符串的方法,比如format,strip等。
  • start_url 初始字符串
  • 2.发送请求,获取响应
  • requests方法,get或者post请求
  • 3.提取数据
  • 返回json字符串:json模块
  • 若返回html字符串:lxml模块
  • 4.保存数据