Hawk教程-动态页面抓取专题
动态页面抓取专题
本文档讨论如何抓取动态页面,包括如何发现真实的数据请求,如何构造并解析请求返回的结果。
1.什么是动态页面?
动态瀑布流和ajax的页面,通常按需返回html和json.
老式网站在刷新时会返回页面的全部内容,但若只更新部分,即可大大节约带宽。该方式叫ajax,服务端传递xml或者json到浏览器,浏览器的js代码执行,并将数据渲染到页面上。 因此,获取数据的真实url,不一定显示在浏览器地址栏,而是隐藏在js调用中。本质上,javascript发起了新的隐藏http请求来获取数据,只要能模拟之,就能像真实浏览器一样获取所要数据。参考百度百科的介绍
2.获取真实数据请求
2.1.Hawk自动获取动态请求
通过浏览器和抓包,可以获取这些隐藏请求,但需要对HTTP请求的原理比较熟悉,不适合于初学者。
Hawk简化了流程,采用自动嗅探的方式来进行。Hawk成为后端代理,会拦截和分析所有系统级Http请求,并将包含关键字的请求筛选出来 (基于fiddler)
当搜索字符时,若没有在当前页面中找到该关键字,Hawk会有提示,“是否启动动态嗅探?”此时Hawk会弹出浏览器并打开所在网页。您可将页面拖到包含关键字的位置,Hawk会自动记录和过滤包含关键字的真实请求, 检索完毕后,Hawk会自动回弹。
2.2.如果无法自动嗅探?
由于Hawk有拦截功能,会被浏览器认为不安全,如何解决呢?
Hawk底层的嗅探基于fiddler,因此可通过fiddler生成证书后,导入到chrome解决,方法可参考这篇文档:
按如下方式对采集器进行设置:
网页采集器请求设置2.3.注意事项
- 有时直接将url拷贝到Hawk,并使用手气不错时,也能获取到数据。这是因为很多网站对第一页和其他页分别作了不同的处理。第一页内容会跟着整体frame返回回来。但之后页面内容就通过ajax单独返回了。
有时针对第一页做了大量的XPath开发,却最后发现无法在其他页面使用,多半就是上面提到的问题(一脸懵逼)。因此经验上,建议翻到其他页面上再做请求。
2.4.手动获取真实请求
即使嗅探失败也没有关系,如果你使用Chrome等浏览器,进入开发者工具(F12):
Chorme的调试窗口设置选择最上角的network卷展栏,之后刷新网页,chrome会列出所有的请求,一般最上面的就是真实请求:
image_1ao1qf5fo1geqsf13be1mpi1lia9.png-68.5kB点击view source,将所有文本,拷贝到网页采集器,对应的高级设置-请求参数里即可。其实,Hawk做的也是类似的操作。
3.请求构造
4.数据后处理
拿到返回的真实数据后,除了用超级模式一步到位解析所需数据之外,还可以通过手动的方式,更灵活地取得所需数据。
4.1.Json处理
Json是最为常见的数据传输格式,也是一棵树。里面包含键值对(字典)和数组,详细信息可以参考文档。
步骤1: 将Json合法化
有时候,网站传过来的json并不是非常合法的json,一些带回调的地址返回的数据,会是如下的形式:
var datas=此处是json;
此时就需要通过字符首尾抽取,或正则表达式和字符串分割等方法,把真正合法的json提取出来。
步骤2: 将字符串转换为文档
上一步获取的结果,依然是个字符串,你需要将其转换为json。 拖入json转换器即可。常见的json有三种模式,我们依次讲解。
类型1:
数据可能位于'data'字段。此处,json转换器应当选择“不进行转换”,转换器本身就不进行任何操作,而是将该json作为整体传到新列里。
之后使用python转换器,脚本内容填写value['data']
. value就是当前列所对应的内容,后面的部分是获取其data。 如果嵌套的更深,你可能需要 value['data1']['data2']
{
'total':12
'data':
[
{ 'key':'value'}
{ 'key':'value'}
]
}
类型2:
这种类型比较少见,是一种纯键值对的字典,我们通常想做的操作,是把内部的键值对都列出来,比如新添key1,key2两个列,内容是value。
方法很简单,json转换器选择"单文档"模式即可。不需要python转换器。
{
'key1':'value'
'key2':'value'
}
类型3:
[
{ 'key':'value'}
{ 'key':'value'}
]
json选择器选择“文档列表”模式即可,不需要python转换器。
所以,看出来了么?json和python转换器的三种工作模式都是一个意思,当你要处理一个数组,就选择文档列表,一个字典,就选择单文档,如果还要取内部更深的信息,就选择不进行转换
。
4.2.json在Hawk的表示问题
由于Hawk的可视化列表中,只能显示字符串和数字,而Json是一棵树,在Hawk中就很难显示.后期会考虑对这块做优化。
如果显示System.Object[], 这表示是一个数组。
如果显示System.Generic.Dictionary... 表示为字典。 也就是文档。
这一块设计得确实非常糟糕,对于一般人来说理解起来太匪夷所思,也是我做得不够好的地方。。。希望能帮到大家。
4.3.用python转换器处理Json
5.案例.
5.1.嗅探
我们以某政府网站的专利检索为例来说明如何使用: ``` http://www.pss-system.gov.cn/sipopublicsearch/patentsearch/showNavigationClassifyNum-showBasicClassifyNumPageByIPC.shtml?params=D7B3D1618C9AC685055FF6612F62529676324C8B6E7F92197ECA1C4E4212C394
示例图如下:
![image_1arbesmq01oucs8so2b6mq2fm9.png-72.7kB](https://img.haomeiwen.com/i9608527/b203c1ac9cc519c8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
不论你点什么样的下拉菜单,url是不变的。我们可以断定这是一个ajax页面。
现在的目标是,通过一个分类号,如`D01B1/00`,来获取它的中文含义和英文含义,也就是右边的内容:
我们启动Hawk,新建一个网页采集器,把刚才的那串url拷贝到网页采集器的地址栏里,发现获取的数据根本不包含这些中文含义。
怎么办呢?
你可以用嗅探,我们将`天然或人造的线或纤维`作为关键字,填写到网页采集器的`内容筛选`里:
![image_1arbf4lfdqpp135k1s2uptkk4m9.png-13.9kB](https://img.haomeiwen.com/i9608527/bfc415b489086f40.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
之后点击`开始`。然后在你的浏览器上点击下拉菜单,展开分类号。发现Hawk已经成功嗅探到了字段:
![image_1arbf64jq15u811nfuei1bsknqcm.png-66.1kB](https://img.haomeiwen.com/i9608527/637397e8b76b954d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
此时,打开`请求属性`,就能看到真正请求的相关信息:
![image_1arbf808c15gjq231kl61c5n1i1j13.png-95.9kB](https://img.haomeiwen.com/i9608527/1f19b70fef533dac.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
这是一次Post请求, (真实地址)url为:
>http://www.pss-system.gov.cn/sipopublicsearch/patentsearch/showNavigationClassifyNumAC!searchChildrenOfClassifyNum.do` post的内容是`classifyNum=D01`。有了这些,我们把这个采集器命名为`专利查询`,下一步就好办了。
即使嗅探失败也没有关系,如果你使用Chrome等浏览器,进入开发者工具(F12):
![Chorme的调试窗口设置](https://img.haomeiwen.com/i9608527/59433d2397073c25.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
选择最上角的network卷展栏,之后刷新网页,chrome会列出所有的请求,一般最上面的就是真实请求:
![image_1ao1qf5fo1geqsf13be1mpi1lia9.png-68.5kB](https://img.haomeiwen.com/i9608527/fc9ef033df1898ff.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
点击view source,将所有文本,拷贝到网页采集器,对应的**高级设置-请求参数**里即可。其实,Hawk做的也是类似的操作。
### 5.2.步骤2:
此处我简单描述一下,你可以新建一个`数据清洗`,生成所有要查询的专利号的ID。这个相对容易。比如拖入`从文本生成`:
![image_1arbfidlrfs95nanvr1d9df511g.png-16.8kB](https://img.haomeiwen.com/i9608527/aaecba7f99226b09.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
再拖入`合并多列`,把这一串ID转换为要post的一列数据:
![image_1arbfl2ska0f1tts1tns1q4t19e81t.png-29.5kB](https://img.haomeiwen.com/i9608527/0a4c93f1e648e433.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
再拖入`添加新列`,因为要让网页采集器访问那个真实数据的url,所以把上面提到的真实地址填进去:
![image_1arbfo6b59qb5km1ore73rjrt2a.png-29.4kB](https://img.haomeiwen.com/i9608527/928aa7fb08de5ba8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
见证奇迹的时刻到了,拖入`从爬虫转换`到刚才的url列,之后如下配置:
![image_1arbfqoa217ggkmf1jhmiaa1ui12n.png-45.5kB](https://img.haomeiwen.com/i9608527/bdd036f3b5a1fb2c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
由于post数据要从post列读入,所以用方括号括起来,像这样`[post]`.
出现了这样的结果:
![image_1arbfsnt1p6oh18vmt8l91dmt34.png-20.8kB](https://img.haomeiwen.com/i9608527/623521d7f91e147c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
这是个Json,因此我们拖入`转换为json`到content列:并将生成模式改为`单文档`,因为这只是一个字典,而不是字典数组:
![image_1arbg0o161t0a1nml10ho1jmu1j9l3h.png-9.5kB](https://img.haomeiwen.com/i9608527/7f1f6350e35729fa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
你会发现只有一列有值:
![image_1arbg20op1dvqvtqfeon531ct93u.png-5kB](https://img.haomeiwen.com/i9608527/a1206525d5e492db.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
是个数组。那么,再拖入`python转换器`,生成模式配置为`文档列表`:
你要的数据就都有了:
![image_1arbg3qee1if195k1pnl1an71uaj4b.png-29.4kB](https://img.haomeiwen.com/i9608527/61e710a89e5d21e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
点评:这种请求,虽然可以用Hawk来配置,不过还是建议使用python,能获取更大的灵活性