【扇贝编程】python爬虫——爬取动态网页笔记
在示例网站上登陆后点开第一条请求(wp-login.php)。右边的 Headers 里可以看到请求地址(Request URL)为 https://wpblog.x0y1.com/wp-login.php,请求方式(Request Method)是 POST,状态码为 302。
POST请求
GET 和 POST 本质上的区别是:
- GET 用于获取数据,比如刷微博;
- POST 用于提交数据,比如登录微博。
GET 和 POST 形式上的区别是:
- GET 的参数显示在请求地址里;
- POST 的参数隐藏在 Form Data 里。
# log 是用户名,pwd 是密码,wp-submit 是提交类型,redirect_to 是登录后的跳转地址
log: codetime
pwd: shanbay520
rememberme: forever
wp-submit: 登录
redirect_to: https://wpblog.x0y1.com
testcookie: 1
requests 库发送 POST 请求
import requests
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
}
data = {
'log': 'codetime',
'pwd': 'shanbay520',
'wp-submit': '登录',
'redirect_to': 'https://wpblog.x0y1.com',
'testcookie': '1'
}
# 由于原来网站SSL证书过期,所以为了结果成功,verify=False,不再验证SSL
requests.post('https://wpblog.x0y1.com/wp-login.php', data=data, headers=headers,,verify=False)
<Response [200]>
在发出 POST
请求之后,服务器会在 Response Headers
(响应头)里返回内容的格式、内容大小、过期时间等信息,这里我们需要的是有关登录的信息——set-cookie
。
set-cookie
的作用是使得之后的操作带有cookie
。cookie
是成功登录的关键。
cookie
cookie
是浏览器储存在用户电脑上的一小段文本文件,里含加密后的用户信息,过期时间等。在 cookie
没有过期之前,再次打开该网站都不再登录。
cookie
失效后,需要重新登录,生成新的 cookie
。
python打印cookie
print(r.cookies)
# <RequestsCookieJar[Cookie(version=0, name='wordpress_logged_in_95afba76913e9e030edc1403a85c976a', value='codetime%7C1725515344%7CKnXwuF20u5WVnW4l1HvHnJJapWLAFxW6dxQSDEhGK5l%7Cca8b184004edbab867b683a52bb3161818f559c34cfa9327be38ed6ca841f63b', port=None, port_specified=False, domain='wpblog.x0y1.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=True, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='wordpress_test_cookie', value='WP+Cookie+check', port=None, port_specified=False, domain='wpblog.x0y1.com', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=True, expires=None, discard=True, comment=None, comment_url=None, rest={}, rfc2109=False), Cookie(version=0, name='wordpress_sec_95afba76913e9e030edc1403a85c976a', value='codetime%7C1725515344%7CKnXwuF20u5WVnW4l1HvHnJJapWLAFxW6dxQSDEhGK5l%7C9917302185b11c9cb7d07709392bf53912954bc5c66e075f4cb72bf725d57baf', port=None, port_specified=False, domain='wpblog.x0y1.com', domain_specified=False, domain_initial_dot=False, path='/wp-admin', path_specified=True, secure=True, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False), Cookie(version=0, name='wordpress_sec_95afba76913e9e030edc1403a85c976a', value='codetime%7C1725515344%7CKnXwuF20u5WVnW4l1HvHnJJapWLAFxW6dxQSDEhGK5l%7C9917302185b11c9cb7d07709392bf53912954bc5c66e075f4cb72bf725d57baf', port=None, port_specified=False, domain='wpblog.x0y1.com', domain_specified=False, domain_initial_dot=False, path='/wp-content/plugins', path_specified=True, secure=True, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)]>
抓取文章
进入分类下的文章页面。
鼠标移到标签旁边,右键点击检查
即可在旁边的开发者工具的元素
里面看到这个文章页面的内容结构:每个标题都是一个 a
标签,其中的 href
属性是链接。
以上述图片为例,<a href="https://wpblog.x0y1.com/?p=211" rel="bookmark">编程实战 – 电商交易流程分析</a>
可以通过标题来获取所有的文章页面链接。
from bs4 import BeautifulSoup
# 发请求登录
login_req = r
# 获取登录后的 cookies
shared_cookies = login_req.cookies
# requests 请求之间的 cookie 不共享
# 将登录后的 cookies 传递给 cookies 参数用于获取文章页面内容
res = requests.get('https://wpblog.x0y1.com/?cat=2', cookies=shared_cookies, headers=headers,verify=False)
# 解析页面
soup = BeautifulSoup(res.text, 'html.parser')
# 选择所有的代表标题的 a 标签
titles = soup.select('h2.entry-title a')
# 先打印结果看看
for i in titles:
print(i)
<a href="https://wpblog.x0y1.com/?p=211" rel="bookmark">编程实战 – 电商交易流程分析</a>
<a href="https://wpblog.x0y1.com/?p=199" rel="bookmark">2006年~2019年中国国内生产总值 (GDP) 统计</a>
<a href="https://wpblog.x0y1.com/?p=43" rel="bookmark">理解二进制难倒了很多人?别急,小贝马上教会你</a>
<a href="https://wpblog.x0y1.com/?p=34" rel="bookmark">Python 环境搭建指南</a>
<a href="https://wpblog.x0y1.com/?p=8" rel="bookmark">因为他,Python 成为当下最红编程语言</a>
对于每个 a
元素,我们需要的是其 href
属性中的链接。通过titles.attrs
的方式,将标签属性以字典的格式返回:
for i in titles:
# 打印标签文本
print(i.text)
# 打印标签属性
print(i.attrs)
编程实战 – 电商交易流程分析
{'href': 'https://wpblog.x0y1.com/?p=211', 'rel': ['bookmark']}
2006年~2019年中国国内生产总值 (GDP) 统计
{'href': 'https://wpblog.x0y1.com/?p=199', 'rel': ['bookmark']}
理解二进制难倒了很多人?别急,小贝马上教会你
{'href': 'https://wpblog.x0y1.com/?p=43', 'rel': ['bookmark']}
Python 环境搭建指南
{'href': 'https://wpblog.x0y1.com/?p=34', 'rel': ['bookmark']}
因为他,Python 成为当下最红编程语言
{'href': 'https://wpblog.x0y1.com/?p=8', 'rel': ['bookmark']}
可以将所有 titles 中所有标题链接放进一个列表中。
links=[]
for i in titles:
links.append(i.attrs['href'])
print(links)
或者
links = [i.attrs['href'] for i in titles]
print(links)
结果为:
['https://wpblog.x0y1.com/?p=211', 'https://wpblog.x0y1.com/?p=199', 'https://wpblog.x0y1.com/?p=43', 'https://wpblog.x0y1.com/?p=34', 'https://wpblog.x0y1.com/?p=8']
session
HTTP
是无状态的,在一次请求、响应结束过后,连接就断开了。
cookie容量有限,只有 4KB。为了保存所有的用户信息需要用到session。我们的所有操作都会被session保留。
requests库支持session
通过 requests.Session()
创建一个 session
,然后就可以像使用 requests
一样使用 session 对象了,get()
、post()
等方法统统都有,只需将原先的 requests
替换成 session
即可。
有了 session
,多个请求之间就可以共享 cookie
。
session的get案例
-
通过
session.headers.update()
方法来定义全局的headers
,通过该session
发送的请求都会默认使用全局headers
。 -
当全局
headers
不满足我们的需求时,也可以给某个请求单独设置headers
。
import requests
session = requests.Session()
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
}
# 设置 session 的全局 headers
session.headers.update(headers)
# 默认使用全局的 headers
session.get('https://wpblog.x0y1.com',verify=False)
# 自定义 headers
custom_headers = { 'referer': 'https://wpblog.x0y1.com' }
session.get('https://wpblog.x0y1.com', headers=custom_headers,verify=False)
# 既有全局的 user-agent 也有自定义的 referer
<Response [200]>
session的post案例
import requests
from bs4 import BeautifulSoup
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'
}
# 登录参数
login_data = {
'log': 'codetime',
'pwd': 'shanbay520',
'wp-submit': '登录',
'redirect_to': 'https://wpblog.x0y1.com',
'testcookie': '1'
}
session = requests.Session()
session.headers.update(headers)
# 使用 session 登录
login_req = session.post('https://wpblog.x0y1.com/wp-login.php', data=login_data,verify=False)
# 使用 session 获得 Python 分类文章
comment_req = session.get('https://wpblog.x0y1.com/?cat=2',verify=False)
# 解析页面
soup = BeautifulSoup(comment_req.text, 'html.parser')
# 选择所有的代表标题的 a 标签
titles = soup.select('h2.entry-title a')
# 获取四篇文章的链接
links = [i.attrs['href'] for i in titles]
for link in links:
# 获取文章页面内容
res_psg = session.get(link,verify=False)
# 解析文章页面
soup_psg = BeautifulSoup(res_psg.text, 'html.parser')
# 获取文章内容的标签
content = soup_psg.select('div.entry-content')[0]
# 打印文章内容
print(content.text)
环节
人数
浏览网站
9943
加入购物车
3320
生成订单
963
支付订单
646
完成交易
412
年份
绝对额(亿元)
同比增长(%)
2006年
219438.5
12.70%
2007年
270092.3
14.20%
2008年
319244.6
9.70%
2009年
348517.7
9.40%
2010年
412119.3
10.60%
2011年
487940.2
9.50%
2012年
538580
7.90%
2013年
592963.2
7.80%
2014年
643563.1
7.30%
2015年
688858.2
6.90%
2016年
746395.1
6.70%
2017年
832035.9
6.90%
2018年
919281.1
6.60%
2019年
990865.1
6.10%
提到进位制,大家应该都对十进制比较熟悉,因为生活中大都使用十进制的,我们从小学就开始学习十进制的四则运算。既然人类对十进制这么熟悉,为什么计算机不和人类使用一样的进制呢?
二进制的表示
计算机底层由一堆电子电路组成,我们来看一个最简单的电路例子:
你可能已经猜到上面电路的功能了:
开关闭合时,灯泡亮
开关断开时,灯泡灭
我们可以用开关闭合代表 1,开关断开代表 0。这就是一个简单的二进制电路。
与此类似,磁盘其实是由很多小磁铁组成的,磁铁的 N 极表示 1,S 极表示 0。所以每个小磁铁和开关一样,也是有 0 和 1 两种状态。
早期的元器件只能表示这两种状态(比如开和关、 N 和 S 等),这就是为什么计算机用的是二进制的原因了。你想想,如果计算机用十进制的话,这个电子元器件得有十种状态,该多么复杂呢!
二进制的位和字节
不过仅用一位数能表示的数字有限,比如二进制是 0-1,十进制是 0-9,十六进制是 0-15。一位数字当然满足不了我们的需求,如果计算机只能处理 0-1 的范围,人类只能处理 0-9 的范围,一个磁盘就只能存储 0 和 1 这两个数字,那么社会发展可能早就停滞不前了吧!
聪明的人类选择用更多的位数来计数,十进制里我们可以用八位数表示亿以内的数字,二进制也是同理。我们一般把 8 位的二进制叫做一个字节(byte)。一个字节能表示 0-255 个值(想想为什么是 255 呢?)。如果想处理更多的信息,就需要更多的位数,比如 64 位的 CPU 能比 32 位的 CPU 处理更多更快的信息。
二进制里“3”的表示
了解这么多了,现在想想如果十进制里的 3,用二进制该怎么表示呢?
其实这个问题和“用十进制表示 9+2”是一样的道理。那就是通过进位。十进制是逢十进一,二进制是逢二进一。
现在我们来看下二进制里怎么表示 3:
上图清晰地展示了二进制里的计算过程,是不是和十进制的进位是一样的逻辑?
1 个字节(8 位的二进制数)里,每个位数权重不一样,分别是 1、2、4、8、16、32、64、128。与此类似,十进制是个、十、百、千、万等等。
现在,你是不是已经弄懂二进制了?
近期在群里看到有小伙伴问,“如何脱离扇贝的环境,在自己的电脑里运行 Python 代码?”。是的,这是一个很好的问题。我们学 Python 是要在真实环境当中使用的,接下来我来给大家介绍一下搭建 Python 环境的常用方法。
Python 有很多种安装方式,这里我们推荐一种最方便快捷的,直接安装 Anaconda,里面内置了 Python、常用第三方模块和用来写代码的 Spyder 编辑器,这简直是懒人神器!
我们有两种安装方式可选:1.官方网站安装 2.清华镜像站安装
网速较慢的同学可以选择第 2 种安装方式。(官方网站为国外源,清华镜像为国内源)
方式一 官方网站安装
点击官网地址:https://www.anaconda.com/products/individual#Downloads
根据自己的系统来选择相应的版本,选择 Graphical Installer 版本进行下载。
如果不清楚自己的 Windows 系统是 64 位还是 32 位,请移步:https://jingyan.baidu.com/article/9f63fb9172d416c8400f0e3b.html
如果是windows,我们可以通过 [我的电脑] 中进行查询:
或者我们也可使用cmd命令行的方式输入systeminfo命令进行查询:
方式二 清华镜像安装
进入清华软件镜像站 Anaconda 的下载页,网址:https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D
找到最新版本的 Anaconda,选择合适的版本下载。
安装包下载好之后,直接打开,看到如下界面。请跟着图中的红框进行操作。
点击 Next 进入下一步
点击 I Agree 进入下一步
选择 Just Me,然后点击 Next 进入下一步
此处可点击 Browse 选择安装位置,然后点击 Next 进入下一步(注意,安装目录中不能有中文,否则安装会报错)
照着图中勾选,然后点击 Install 进行安装
稍等片刻后,点击 Next 进入下一步
直接点击 Next 进入下一步
点击 Finish 完成安装,如何不想看官方介绍可以取消两个勾选
新版本的anaconda还会有Kite的选择安装,Kite是一个非常实用的代码补全工具,可以选择安装让它成为你的得力助手!当然如果没有安装的话也不担心哦,因为anaconda作为一个非常优秀的代码编译器集成环境,spyder也有自带的代码补全功能,所以问题不大哦~
OK,到这里我们就完成全部的安装工作啦!
下面讲解如何使用 Anaconda 中的 Spyder 编写代码!
Spyder 的用法
在开始菜单中找到并打开 Anaconda Navigator。
然后会出现如下初始化界面。
初始化中…
稍等片刻后将出现如下界面:
点击绿色按钮
找到 Spyder,点击 Launch。
打开后,看到如下界面,我们就可以在里面写代码了。
Spyder会是一个集成度非常高的编译器,先简单介绍以下Spyder界面:
在左上角你可以切换为文件管理File,这样你就能看到工作路径空间里的对应内容了:
有学员可能会问到,如果我需要中文版的Spyder怎么办,别着急,接下来教你如何将语言切换为中文:
我们可以直接在默认的 temp.py 里写代码,也可以点击 文件 – 新建文件,创建一个新的 py 文件来写代码。
写好代码后,点击运行按钮即可运行 Python 代码啦~
第一次运行代码时,需要设置一下执行配置,直接点击运行即可。
然后我们就能在控制台看到代码的运行结果啦~
如果你想将temp.py重命名,只需要对其另存为即可修改它的名字~
Anaconda 中已经包含了我们课程中需要的绝大多数第三方模块,因此可以不用再使用 pip install 模块名 来安装第三方模块了。
爬虫课中的 selenium 模块并没有内置在 Anaconda 中,安装方法如下(其他第三方模块也类似):
点击 Anaconda Navigator 中的 Environments 面板
将右边的单选框选择为 All
在搜索框中输入要安装的第三方模块,比如 selenium
选中要安装的模块,注意要选名称完全一样的
点击右下角的 Apply 按钮
如果输入 selenium 后没有结果,点击 Channels 和 Update index 按钮试试~
然后会出现这样一个界面,直接点击 Apply 按钮即可安装。
稍等片刻后,模块便安装完毕,即可在代码中使用啦~
当然,anaconda为我们提供了一个非常强大的命令行工具:anaconda prompt 我们可以通过它来进行第三方库的安装。
在开始菜单 anaconda 目录下找到 anaconda prompt
可以利用 pip install [第三方库名] 进行安装
也可以利用anaconda自身的 conda install [第三方库名] 进行安装
两者效果是一样的,都能直接安装在 anaconda 的python环境中。
Spyder画图显示问题
学到后面的课程可能会涉及到画图问题,为了避免这种问题的出现,我们可以提前设置好一些画图的内容,省下后续的麻烦。
默认的设置是画图在inline画在Spyder界面中哦,我们可以点击左上区域中的Plots即可看到图片。
我们可以通过修改配置,修改为 Automatic 即 自动,即可让Spyder以弹窗的方式画图。
别忘了设置完重启Spyder 的 console 或者 更暴力一点,重启Spyder。
“我累了,需要很长时间的休息”
在 2018 年 7 月的一份名为“权力转移”的邮件列表帖子中,Guido van Rossum 写道:
“我不想再为 PEP 劳神了,而且尽管我做着艰难的决定,却发现仍然有很多人不满意。”
Guido van Rossum 部分邮件截图
“PEP” 是一种 Python 改进提案(Python Enhancement Proposal )。Guido 会亲自签署并确认每一份 PEP ,这也是他被称为仁慈的独裁者的一个原因。与此形成鲜明对比的是,PHP 的类似改进都是通过投票完成的。
Guido 对 Python 无疑是精益求精的——但 PEP 572 被接受后的第三天,雪片一样飞来的反馈意见让这个今年已经 62 岁的著名工程师应接不暇。
他出生在一个荷兰小城哈勒姆,于 1982 年毕业于荷兰的阿姆斯特丹大学的数学和计算机科学专业。随后进入了阿姆斯特丹的数学和计算机科学中心,成为了一名程序员。
在CWI ,蟒爹一干就是 12 年,直到 1994 年才离开。1989 年圣诞节期间,蟒爹为了打发无聊的圣诞假期,(???原来大神都是这么打发时间的)决心开发一个新的脚本解释程序,作为 ABC 语言的一种继承。
之所以选中 Python 作为程序的名字,是因为他非常喜欢一部英国肥皂剧:《Monty Python 飞行马戏团》。他觉得 Python 这个词非常有趣,很吸引人,从 Python 的命名就可以看出蟒爹对它的珍爱。
自 1989 年 Python 诞生,这位耿直的工程师倾尽了 30 年的心血不断完善它,这才有了如今的 Python 。
蟒爹穿着写有“人生苦短,我用 Python ”的T恤与大家合影
“我仍然会在这里”
“作为一个普通的核心开发者,我仍然会一直都在,而且我仍然可以指导人,或许可能有更多的时间。”
他补充说:“但我基本上给自己放了一个永久的假期不当 BDFL(Benevolent Dictator For Life),接下来你们就靠自己了。”
不论 Python 团队的人员如何变动,不可否认的是使用它的人越来越多了。
2018年7月编程语言指数榜
CodingDojo 最近将 Python 评为开发人员招聘广告中第二大最受欢迎的技能。Stack Overflow 的 2018 年开发人员调查将 Python 列为第七大流行的“编程、脚本和标记语言”,领先于 C#,Ruby 和 PHP。
事实证明,蟒爹的成就是非凡的:Python 成为世界上使用最多的语言之一。
在机器学习,人工智能,科学计算,金融,游戏,数学,物理等各个领域都有大量使用。各个大学和各大公司包括 Google,Facebook ,微软,阿里巴巴等,也都在使用 Python 。
“人生苦短,Python 是岸”
Python 是一种理想的初学者语言,也被用于重量级企业应用程序。
它的设计非常简单、优雅、清晰。
最主要的是,Python 是人工智能首先的编程语言——它在人工智能上的优势至今无人能够撼动。
Python 语言因此广受程序员的追捧,而其在就业、薪资待遇上也没有让人失望。
去年,职友集通过分析来自全国的 12809 份样例资料,显示全国 Python 工程师的平均月资能够达到 19160 元,其中 20 – 30 K 的工程师数量更是超过了四成。对程序员而言,Python 可能是一门投入小,但见效快、回报还高的编程语言。
其实正如蟒爹曾在致中国读者信中所写:
“ Python 这门语言让人们的生活变得更加便捷。它可以使你把精力集中于手头的工作,而不是纠缠于计算机系统每一个晦涩难懂的细节。”