前言
本篇的内容接上一篇,主要讲的是AJAX,JSON解析和正则表达式。
我这里不重复注意事项,如果你有不明确的请去看一下上一篇爬虫基础。
AJAX交互:在使用网页中,有时候需要获取的信息放在对面服务器里并不会直接给你,而是需要你通过查询的方式才会返回相应的数据,返回的不是一整个网页,而是你所需要的数据,这样子可以减少服务器的带宽占用。
JSON是一种轻量级资料交换格式,其内容由属性和值所组成,因此也有易于阅读和处理的优势,所以大多数服务器的数据发送接收都采用JSON格式。
正则表达式作为用简单字符串来描述、匹配文中全部匹配指定格式的字符串,现在很多文本编辑器都支持用正则表达式搜索、取代匹配指定格式的字符串,检索效率能快不少。
AJAX
传统的Web允许用户端填写表单(form),当提交表单时就向网页服务器发送一个请求。服务器接收并处理传来的表单,然后送回一个新的网页,但这个做法浪费了许多带宽,因为在前后两个页面中的大部分HTML码往往是相同的。由于每次应用的沟通都需要向服务器发送请求,应用的回应时间依赖于服务器的回应时间。这导致了用户界面的回应比本机应用慢得多。
与此不同,AJAX应用可以仅向服务器发送并取回必须的数据,而不是整个网页,并在客户端采用JavaScript处理来自服务器的回应。因为在服务器和浏览器之间交换的数据大量减少,服务器回应更快了。同时,很多的处理工作可以在发出请求的客户端机器上完成,因此Web服务器的负荷也减少了。
我们这里以肯德基餐厅信息查询网站作为示例,演示AJAX的特征和交互方式,以及数据获取方式。
其他很多网站都是大同小异,你还可以去一些国家政务网站资料查询那里尝试,不过一次请求就够了别短时间爬取太多次,记住之前说的注意事项就行。
当你进行一次请求或者刷新操作时,网页只有一部分内容发生了变化,网址没有变化。
类似于这样
或者说网址变化了,但是你用爬虫请求该网页时,发现本该出现的数据没有出现。
例如
我们先打开肯德基餐厅信息查询网站,然后打开浏览器控制台,然后在搜索框做一次请求,在网络选项卡下面就可以看到我们做的请求了,如果请求过多不好定位,可以在类别筛选里面选择AJAX
或者叫Fetch/XHR
来快速找到对应请求。
这里可以看到我们做出查询的关键词来定位我们的请求。
在响应里面可以找到服务器返回给我们的数据。
因为太多这里只展示一部分。
1 | { |
接下来我们回到标头可以看到我们请求的网址,请求方法是POST
还是GET
,以及携带的表单,或者叫数据。这些数据向我们展示了如何规范地向服务区索取对应的数据,网址,格式,页码,参数等等。我们接下来的爬虫程序跟着做就行。
在前面的基础上面我们只需要对我们的请求加一点东西即可完成AJAX请求,可以看到,我们这次请求方法是POST
,网址是
http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword
,数据如上。如果要请求相同到的东西,我们只需要写出下面的代码即可。
1 | import requests |
这里的header上次讲过了,data的参数在POST里对应的就是你要向服务器提交的表单。URL对应的是上面POST请求的URL,不是你网址栏的URL
这样子,你就成功拿到了你想要的数据。
JSON解析
上面我们成功拿到了数据,但是是JSON字符串格式的,我们只需要里面某个类别的数据,比如所有餐馆的名字,那该怎么办呢?
现在就是让我们解析JSON格式数据输出的时候了。
想要使用官方自带的JSON库,我们照例还是得添加一行导入。
1 | import json |
然后我们得把获取到的JSON数据转化为字典。
我把下面JSON格式化只是让你们看清楚层级关系,你们拿到手的JSON文本都被压缩成了一整行,想要像这样子的话网络上面有很多格式化网站可供使用。
这样子很清楚能看到层级关系,方便数据解析操作。
1 | js = '''{ |
这样子r
这个变量就变成了存储JSON的字典,按照PYTHON字典的方式控制即可
例如下面的代码就是把里面详细地址的值打印出来。
1 | print(r["Table1"][0]["addressDetail"]) |
正则表达式
由于讲起来可是一门很深的学问,而且挺难的,所以这里就不细讲,主要也是因为自己水平也不过关,主要说最常用的匹配操作。
以后看各位需要再看要不要跟这次爬虫一样拆成几次讲完。
这个作为强大的处理工具,按理来说你使用熟练的话可以取代掉很多其他工具的数据解析工作。比如之前的lxml,JSON,bs等等。
在Python里,用re
模块来导入相应的库。
接下来书写正则表达式
例子:(把下面的google链接提取出来)
可以这样写程序:
1 | import re |
1 | <script async=.*?async="" src="(.*?)"></script>.*?</script> |
这句表达式里面,上面一共有三个.*?
,他们连在一起代表匹配多个任意字符
如果你把普通字符写在正则里面代表匹配特定字符。上面表达式的效果,匹配字符串中在async="" src="
和"></script>
中间的内容,也就是https://www.googletagmanager.com/gtag/js?id=G-9JKZ3LJVCD
带括号的代表你要查找的部分。re.S
代表查找模式,一般数据解析只需要用这个模式就行。
这就是本篇所有内容了,感谢你的观看,如果有建议或者错误请指出,感谢。