第一章 开发环境配置

略(遇到再补充)

第二章 爬虫基础

HTTP和HTTPS
URL的开头会有http和https,这是访问资源需要的协议类型。有时,我们还会看到ftp、sftp、smb开头的URL,他们都是协议类型。在爬虫中,我们抓取的页面通常就是 http 或 https 协议的。
HTTP 中文名叫做超文本传输协议,目前广泛使用的是 HTTP 1.1 版本。
HTTPS简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL 层,简称为HTTPS。
而某些网站虽然使用了 HTTPS 协议还是会被浏览器提示不安全,例如 12306。这是因为 12306 的 CA 证书是中国铁道部自己颁发给自己的,而这个证书是不被官方机构认可的,所以这里证书验证就不会通过而提示这样的话,但是实际上它的数据传输依然是经过 SSL 加密的。我们如果要爬取这样的站点就需要设置忽略证书的选项,否则会提示 SSL 链接错误,在后文会进行详细说明。

网页基础
网页分为三大部分——HTML、CSS和JavaScript。

F12 右侧 HTML,整个网页由各种标签嵌套组合而成,这些标签定义的节点元素相互嵌套和组合形成复杂的层次关系,就形成了网页的框架。
左侧为CSS ,CSS 层叠样式表。样式指网页中文字大小、颜色、元素间距、排列等格式。它可以让页面变得更美观。

JavaScript,简称js 为网页提供实时,动态,交互的页面功能。js通常以单独的文件形式加载,后缀为js,通过script标签引入。
html、css、js 都是前端
asp、jsp、php… 是后端

页面的结构
新建一个文本文件,重命名为1.html。内容如下:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>This is a test</title>
</head>
<body>
<div id="container"><div class="wrapper"><h2 class="text">hello world</h2><p class="text">hello,this is a paragraph.</p>        </div>
</div>
</body>
</html>

html的后缀有 .html 或htm
DOCTYPE html 定义文档类型

<html> html的开头 </html> 文件结尾
<head>文件头开始
<body>文件主体开开始

虽然html是门松散的语言,但是为了良好的编程习惯,平时使用时这些标签最好成对使用。(不允许交替出现)
meta标记 是头文件里面的,定义相关信息。
meta name=“……” content=“……” 这类类型可以帮助搜索引擎收录


第三章 基本库的使用

使用request

使用get()访问百度

import requestsr=requests.get('https://www.baidu.com/')
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text)
print(r.cookies)


我们使用get()方式得到一个 Response的对象。
<class ‘requests.models.Response’>
使用其他的请求类型

get请求
HTTP中最常见的请求之一就是GET请求

import requestsr=requests.get('http://www.httpbin.org/get')
print(r.text)


一般get请求带参数,可以使用下面两种方法:

或者:

import requestsdata={'name':'abcd','age':18
}
r=requests.get('http://www.httpbin.org/get',params=data)print(r.text)

上面的截图可以看到,页面的返回类型是str类型,是json格式。
如果想直接解析返回结果,得到一个字典格式,可以直接调用json()方法。


可以发现,调用 json()方法,就可以将返回结果是 JSON 格式的字符串转化为字典。但需要注意的书,如果返回结果不是 JSON 格式,便会出现解析错误,抛出 json.decoder. JSQNOecodeError异常。

带参数的POST请求
和上面类似

import requests#带参数的post
data={'name':'abcd','age':'13'
}
r=requests.post('http://www.httpbin.org/post',data=data)
print(r.text)

增加heads(尝试抓取知乎——发现)

状态码400,网站有防爬
加入UA头后可以爬

使用正则表达获取我们想要的信息(文章标题)
观察我们爬到的数据,和我们想要的信息

抓取二进制数据
如果要抓取图片、音频、视频等文件。
下面以GitHub的站点图标(https://github.com/favicon.ico)为例
采用r.text 会出现乱码

使用r.content 输出二进制
前面的b‘表示二进制

import requestsr=requests.get('https://github.com/favicon.ico')
# print(r.content)
with open('fa.ico','wb') as f:f.write(r.content)

运行后发现文件夹内多出一个图标

同样的其他类型的文件也可以采用这种方法获取

获取响应内容
可以获取状态码、响应头、cookies等

import requests#响应
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'}
r=requests.get('http://www.jianshu.com',headers=headers)
print(type(r.status_code),r.status_code)
print(type(r.headers),r.headers)
print(type(r.cookies),r.cookies)
print(type(r.url),r.url)
print(type(r.history),r.history)

文件上传
假如网站需要上传文件

import requestsfiles={'file':open('fa.ico','rb')}
r=requests.post('http://www.httpbin.org/post',files=files)
print(r.text)

cookies

import requests#cookies
r=requests.get("https://www.baidu.com")
print(r.cookies)
for key,value in r.cookies.items():print(key+'='+value)

首先调用cookies属性,成功得到cookies,它是requestcookieJar类型。然后用items()方法,遍历出每一个cookie的名称和值,实现cookie的遍历解析。

使用cookie维持登录状态,下面以知乎为例

将cookie复制到headers后内容,再运行程序。结果中显示出登录后的结果,说明登录成功。

会话维持
在 requests 中,如果直接利用 get ()或 post ()等方法的确可以做到模拟网页的请求,但是这实际上是相当于不同的会话,也就是说相当于你用了两个浏览器打开了不同的页面。

import requests
#session
requests.get('http://httpbin.org/cookies/set/number/123456789')#这个网站可以把cookie的值设置成123456789
r=requests.get('http://httpbin.org/cookies')#这个网站可以显示cookie的值
print(r.text)


说明两次requests调用了不同会话
下面使用session,get请求在一个会话里

import requests
#session
s=requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')#这个网站可以把cookie的值设置成123456789
r=s.get('http://httpbin.org/cookies')#这个网站可以显示cookie的值
print(r.text)

所以,利用 Session ,可以做到模拟同一个会话而不用担心 Cookies 的问题。 它通常用于模拟登录成功之后再进行下一步的操作 。Session 在平常用得非常广泛,可以用于模拟在一个浏览器中打开同一站点的不同页面。
SSL证书
12306,我这边测试的时候访问是正常显示。可能和书本里的情况不太一样了,先记录下笔记
当出现SSLError错误的时候(证书验证错误),将verify设置成Flase即可

import requests
#SSL证书
response=requests.get('https://www.12306.cn',verify=False)
print(response.status_code)

但会收到警告

代理设置

import requestsproxies={"http":"http://代理","https":"http://代理"
}
requests.get("http://www.httpbin.org/get",proxies=proxies)

正则表达

开源中国提供的正则表达测试工具:http://tool.oschina.net/regex/
待输入文本:

Hello, my phone number is 010-86432100 and email is cqc@cuiqingcai.com, and my website is https://cuiqingcai.com.

尝试用正则表达式提出电话号码,url
url:

[a-zA-z]+://[^\s]*

电话:

\d{3}-\d{8}|\d{4}-\{7,8}

正则匹配规则
python的re库提供了正则表达的实现
match()
match()方法尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配,就返回none

import recontent='Hello 123 4567 World_This is a Regex Demo'
print(len(content))
result=re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}',content)
print(result)
print(result.group())
print(result.span())

\w:匹配字母、数字、下划线。等价于’[A-Za-z0-9_]’
\s:匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
结果:

打印输出结果,可以看到结果是 re.Match 对象,这证明成功匹配。 该对象有两个方法: group()
方法可以输出匹配到的内容,结果是 Hello 123 4567 World This ,这恰好是正则表达式规则所匹配的
内容; span()方法可以输出匹配的范围,结果是(0’ 25 ),这就是匹配到的结果字符串在原字符串中的位置范围 。

匹配目标
用()括号将想提取的子字符串括起来。()实际上标记了一个子表达式的开始和结束位置,被标记的每个子表达式会依次对应每一个分组,调用 group()方法传入分组的索引即可获取提取的结果。 示例如下 :

content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^Hello\s(\d+)\sWorld',content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())

这里我们想把字符串中的 1234567 提取出来, 此时可以将数字部分的正则表达式用()括起来, 然后调用了 group(1)获取匹配结果。

可以看到,我们成功得到了 1234567 。 这里用的是 group(1),它与 group()有所不同,后者会输出完整的匹配结果,而前者会输出第一个被()包围的匹配结果 。 假如正则表达式后面还有()包括的内容,那么可以依次用 group(2)、group(3)等来获取。

贪婪与非贪婪

import re#贪婪与非贪婪
content='Hello 1234567 World_This is a Regex Demo'
result=re.match('^He.*?(\d+).*?Demo$',content)
result2=re.match('^He.*?(\d+).*Demo$',content)
result3=re.match('^He.*(\d+).*Demo$',content)
print(result.group(1))
print(result2.group(1))
print(result3.group(1))


这里就涉及一个贪婪匹配与非贪婪匹配的问题了 。 在贪婪匹配下.*会匹配尽可能多的字符。 正则表达式中.*后面是\d+,也就是至少一个数字,并没有指定具体多少个数字,因此,就尽可能匹配多的字符,这里就把 123456 匹配了,给\d+留下一个可满足条件的数字 7 ,最后得到的内容就只有数字 7 了 。
非贪婪模式可以成功获取 1234567 了 。 原因可想而知,贪婪匹配是尽可能匹配多的字符,非贪婪匹配就是尽可能匹配少的字符。 当.*?匹配到 Hello 后面的空向字符时,再往后的字符就是数字了 ,而\d+恰好可以匹配 ,那么这里.的就不再进行匹配,交给\d+去匹配后面的数字。 所以这样.叫匹配了尽可能少的字符,\d+的结果就是 1234567 了 。
但这里需要注意,如果匹配的结果在字符串结尾,.*?就有可能匹配不到任何内容了,因为它会匹配尽可能少的字符。

修饰符
和上面的例子相仿,我们在字符串中加了换行符,正则表达式是一样的,用来匹配其中的数字:

程序报错,因为遇到换行。这里只需要加一个修饰符 re.S

import re#修饰符
content='''Hello 1234567 World_Thisis a Regex Demo'''
result=re.match('^He.*?(\d+).*?Demo$',content,re.S)
print(result.group(1))

这个 re.S 在网页匹配中经常用到 。 因为 HTML 节点经常会有换行,加上它,就可以匹配节点与节点之间的换行了 。
修饰符:
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响^和$
re.S 使.匹配包括换行符在内的所有字符
re.U 根据unicode 字符集解析字符。这个标志影响\w,\W,\b和\B
re.X 该标志通过给予更灵活的格式以便你将正则表达式写得更易于理解
在网页匹配中,较为常用的有se.S和re.I

seach()
match()方法是从字符串的开头开始匹配,一旦开头不匹配,那么整个匹配就失败了。

将上述代码中的match()方法修改成search(),再运行,就能得到匹配结果。平时使用的时候,尽量用search()

import re
#search()
content='Extra stings Hello 1234567 World_This is a Regex Demo'
result=re.search('He.*?(\d+).*?Demo',content)
print(result)
print(result.group(1))

这里就有另外一个方法 search(),它在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果 。也就是说,正则表达式可以是字符串的一部分,在匹配时, search()方法会依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完了还没有找到,就返回 None。

用正则信息提取:

<div id="songs-list" >
<h2 class "title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2 ">一路上有你</li>
<li data-view="7">
<a href ="/2.mp3 " singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3 .mp3 " singer="齐泰">往事随风 </a>
</li>
<li data-view="6">< a href="/4.mp3 "singer=" beyond">光辉岁月 </a></li>
<li data-view="5"><a href="/S.mp3 " singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3 " singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>

这里尝试自己编写代码时发现使用search()只能匹配到第一个内容。这里需要使用findall(),我写的代码:

import re#正则提歌
html='''<div id="songs-list" >
<h2 class "title">经典老歌</h2>
<p class="introduction">
经典老歌列表
</p>
<ul id="list" class="list-group">
<li data-view="2 ">一路上有你</li>
<li data-view="7">
<a href ="/2.mp3 " singer="任贤齐">沧海一声笑</a>
</li>
<li data-view="4" class="active">
<a href="/3 .mp3 " singer="齐泰">往事随风 </a>
</li>
<li data-view="6">< a href="/4.mp3 "singer=" beyond">光辉岁月 </a></li>
<li data-view="5"><a href="/S.mp3 " singer="陈慧琳">记事本</a></li>
<li data-view="5">
<a href="/6.mp3 " singer="邓丽君">但愿人长久</a>
</li>
</ul>
</div>'''result=re.findall('singer="(.*?)">(.*?)</a>',html,re.S)
print(result)
for i in result:print(i)

HTML有换行,这里要使用re.S修饰符

sub()
除了使用正则表达式提取信息外,有时候还需要借助它来修改文本 。 比如,想要把一串文本中的所有数字或非数字都去掉。

import re#sub()
content='54jeioru98q3u999890797dudoi'
content1=re.sub('\d+','',content)
content2=re.sub('\D+','',content)
print(content1)
print(content2)

compile()
这个方法可以将正则字符串编译成正则表达式对象,以便在以后的匹配中复用。

import re#compile()
content='2020-09-21 09:16:50'
content1='2020-09-25 09:16:16'
content2='2020-09-27 09:16:55'
pattern=re.compile('\d{2}:\d{2}:\d{2}')
result=re.sub(pattern,'',content)
result1=re.sub(pattern,'',content1)
result2=re.sub(pattern,'',content2)
print(result,result1,result2)


这里用sub()方法,去掉时间,只留下日期。sub(),第一参数是正则表达式,这里不用重复写三次,而是借助compile()方法将正则表达式编译成一个正则表达对象,以便重复使用。此外,compile()方法还可以传入修饰符,如re.S。所以,compile()方法可以说是给正则表达式做了一层封装,以使我们更好地复用 。

实战(抓取猫眼电影排行)

目标网站:https://maoyan.com/board/4
先尝试自己编写

import requests
import re
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'}
for k in range(0,100,10):url='https://maoyan.com/board/4?offset='+str(k)r=requests.get(url,headers=headers)content=r.textresult=re.findall('<p class="name"><a href="/films/\d+" title="(.*?)" data-act=',content,re.S)print(result)


成功!看下书本的内容
书里除了抓取名字还抓取了演员,时间,评分等信息,使用了字典,输出到了文件

【读书笔记】python3 网络爬虫开发实战(1)相关推荐

  1. 《崔庆才Python3网络爬虫开发实战教程》学习笔记(3):抓取猫眼电影榜单TOP100电影,并存入Excel表格

    本篇博文是自己在学习崔庆才的<Python3网络爬虫开发实战教程>的学习笔记系列,如果你也要这套视频教程的话,关注我公众号[小众技术],关注后回复[PYTHON],无套路免费送你一个学习大 ...

  2. 《崔庆才Python3网络爬虫开发实战教程》学习笔记(5):将爬虫爬取到的数据存储到TXT,Word,Excel,Json等文件中

    本篇博文是自己在学习崔庆才的<Python3网络爬虫开发实战教程>的学习笔记系列,此套教程共5章,加起来共有34节课,内容非常详细丰富!如果你也要这套视频教程的话,关注我公众号[小众技术] ...

  3. 《崔庆才Python3网络爬虫开发实战教程》学习笔记(4):解析库Xpath的使用方法总结

    本篇博文是自己在学习崔庆才的<Python3网络爬虫开发实战教程>的学习笔记系列,如果你也要这套视频教程的话,关注我公众号[小众技术],关注后回复[PYTHON],无套路免费送你一个学习大 ...

  4. python3网络爬虫开发实战学习笔记(二)------python3 XPATH爬 猫眼电影排名

    我最近在看崔庆才老师的<python3 网络爬虫开发实战>觉得挺不错的,上面还有一个 用正则表达式爬取猫眼电影的电影排行榜 我练了一下,感觉不会很难,后来学到了xpath,就想用xpath ...

  5. [Python3网络爬虫开发实战] --分析Ajax爬取今日头条街拍美图

    [Python3网络爬虫开发实战] --分析Ajax爬取今日头条街拍美图 学习笔记--爬取今日头条街拍美图 准备工作 抓取分析 实战演练 学习笔记–爬取今日头条街拍美图 尝试通过分析Ajax请求来抓取 ...

  6. [Python3网络爬虫开发实战] 7-动态渲染页面爬取-4-使用Selenium爬取淘宝商品

    在前一章中,我们已经成功尝试分析Ajax来抓取相关数据,但是并不是所有页面都可以通过分析Ajax来完成抓取.比如,淘宝,它的整个页面数据确实也是通过Ajax获取的,但是这些Ajax接口参数比较复杂,可 ...

  7. 【Python3网络爬虫开发实战】3-基本库的使用 1.2-处理异常

    前一节我们了解了请求的发送过程,但是在网络不好的情况下,如果出现了异常,该怎么办呢?这时如果不处理这些异常,程序很可能因报错而终止运行,所以异常处理还是十分有必要的. urllib的error模块定义 ...

  8. 《Python3网络爬虫开发实战(第二版)》上市了!!!!

    " 阅读本文大概需要 5 分钟. " 告诉大家一个好消息:我的好朋友崔庆才老师的<Python3网络爬虫开发实战(第二版)>现在正式上市了!!!! 没错,就是这本: 就 ...

  9. python3网络爬虫代码_《Python3网络爬虫开发实战代码》

    <Python3网络爬虫开发实战代码>\appium\.git\COMMIT_EDITMSG, 7 , 2017-08-15 <Python3网络爬虫开发实战代码>\appiu ...

  10. 【Python3网络爬虫开发实战】4-解析库的使用-3 使用pyquery

    在上一节中,我们介绍了Beautiful Soup的用法,它是一个非常强大的网页解析库,你是否觉得它的一些方法用起来有点不适应?有没有觉得它的CSS选择器的功能没有那么强大? 如果你对Web有所涉及, ...

最新文章

  1. linux 系统 UDP 丢包问题分析思路
  2. 很遗憾,没有一篇文章能讲清楚ZooKeeper
  3. Python函数的定义和使用
  4. 【Python】学习笔记总结3(Python文件操作)
  5. FluentNhibernate 组件component及应用
  6. 合并和排序 Linux 上的文件
  7. 深度学习2.0-35.ResNet-18实战
  8. 南昌工程学院计算机考试题库和答案,南昌工程学院 语试题答案.doc
  9. 笔记-51,k60,stm32
  10. 电信物联网平台对接教程
  11. 智能名片小程序名片详情页功能实现关键代码
  12. go-优雅地重启http服务之endless
  13. tcp服务器响应超时,tcp客户端与服务器的连接超时
  14. SEO优化基础:SEO的优势与劣势
  15. npm ERR! Error: tunneling socket could not be established的解决问题
  16. 2022群发邮件软件有哪些?哪个好用呢?解读如何大量群发邮件及单显功能
  17. 数据库常见的安全问题有哪些?
  18. chrome无法添加.crx文件(扩展程序)
  19. 随机系统(stochastic systems)——以随机游走为例
  20. winserver修改计算机用户名,如何修改Windows系统的管理员账户名

热门文章

  1. 尚学堂马士兵struts2 课堂笔记(一)
  2. wpf OpenClipBoard CLIPBRD_E_CANT_OPEN
  3. java myqq ui_GitHub - 744184755/myqq: Java版SWing“高”仿QQ即时通聊天系统
  4. Serv-U FTP - v15.3.1.155特别版
  5. 黑屏后面藏了什么?--解读微软打击盗版
  6. 计算机应用为什么要学机械制图,简述机械制图学习的重要性
  7. stuxnet震网病毒科普
  8. Java设计模式——简单工厂模式
  9. 变速精灵 3.0免费版
  10. 跨境电商独立站,如何找到更多联盟流量资源