爬虫入门到精通-爬虫之异步加载(实战花瓣网)

本文章属于爬虫入门到精通系统教程第八讲

本次我们会讲解两个知识点

  1. 异步加载
  2. headers中的Accept

本次我们要抓取的是花瓣网美女照片美女花瓣,陪你做生活的设计师(发现、采集你喜欢的美女图片)花瓣网(http://huaban.com/favorite/beauty/)

本次我们会用到的辅助包

scrapy/parsel (https://github.com/scrapy/parsel)(假如你用过scrapy,那么一定不陌生,这就是其中提取器)
Parsel is a library to extract data from HTML and XML using XPath and CSS selectors
简单来讲就是集成了xpath和css,只要你会xpath的话,那么用法没有什么区别
 >>> from parsel import Selector  >>> sel = Selector(text=u"""<html>          <body>              <h1>Hello, Parsel!</h1>              <ul>                  <li><a href="http://example.com">Link 1</a></li>                  <li><a href="http://scrapy.org">Link 2</a></li>              </ul          </body>          </html>""")  >>>  >>> sel.css('h1::text').extract_first()  u'Hello, Parsel!'  >>>  >>> sel.css('h1::text').re('\w+')  [u'Hello', u'Parsel']  >>>  >>> for e in sel.css('ul > li'):          print(e.xpath('.//a/@href').extract_first())  http://example.com  http://scrapy.org
安装方法: pip install parsel
scrapinghub/js2xml(https://github.com/scrapinghub/js2xml)
Convert Javascript code to an XML document
简单来讲就是 将JavaScript代码转换为xml文档。然后可以使用xpath从JavaScript中提取数据,不用写一堆正则了。
 >>> import js2xml  >>>  >>> jscode = """function factorial(n) {  ...     if (n === 0) {  ...         return 1;  ...     }  ...     return n * factorial(n - 1);  ... }"""  >>> parsed = js2xml.parse(jscode)  >>>  >>> parsed.xpath("//funcdecl/@name")  # extracts function name  ['factorial']  >>>  >>> print js2xml.pretty_print(parsed)  # pretty-print generated XML  <program>    <funcdecl name="factorial">      <parameters>        <identifier name="n"/>      </parameters>      <body>        <if>          <predicate>            <binaryoperation operation="===">              <left>                <identifier name="n"/>              </left>              <right>                <number value="0"/>              </right>            </binaryoperation>          </predicate>          <then>            <block>              <return>                <number value="1"/>              </return>            </block>          </then>        </if>        <return>          <binaryoperation operation="*">            <left>              <identifier name="n"/>            </left>            <right>              <functioncall>                <function>                  <identifier name="factorial"/>                </function>                <arguments>                  <binaryoperation operation="-">                    <left>                      <identifier name="n"/>                    </left>                    <right>                      <number value="1"/>                    </right>                  </binaryoperation>                </arguments>              </functioncall>            </right>          </binaryoperation>        </return>      </body>    </funcdecl>  </program>
安装方法: `pip install js2xml`

开始爬虫

我们先打开美女花瓣,陪你做生活的设计师(发现、采集你喜欢的美女图片)花瓣网(http://huaban.com/favorite/beauty/)

页面分析

如果我们想把这里面所有美女照片抓取下来的话,那么我们的操作步骤应该是这样的

1.打开首页的每一个”相框”,然后点进去

2.获取所有图片的链接,然后下载下来

程序实现:

用程序实现的话,也是挺简单的

  1. 获取首页所有“相框”的链接
  2. 点进去每个链接
  3. 获取详情页的所有图片地址
  4. 下载图片

代码:

  1. 获取首页所有“相框”的链接
    1. //a[@class=”img x layer-view loaded”]/@href
    2. 我们打开美女花瓣,陪你做生活的设计师(发现、采集你喜欢的美女图片)花瓣网(http://huaban.com/favorite/beauty/)
    3. 按F12
    4. 点击如图所示的位置
    1. 点击任何一个相框,然后你会看到网页的源代码自动会跳到你当前选中的地方
    1. 然后你就可以在这附近找找你想要的链接地址(可以看到/pins/1062650100/,我们可以打开这个地址看看,确认下是我们想要找的)
    1. 可以看到图片是一样的,说明我们要找的没错
    1. 那么既然我们找到了需要的链接,接下来就是用程序定位到这了。
    2. 可以看到链接这边有个class=”img x layer-view loaded”,那么我们可以用以下xpath来获取地址了

用代码实现:

import requests
from parsel import Selector
url = ‘http://huaban.com/favorite/beauty/‘
headers = {‘User-Agent’:’Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36’}
z = requests.get(url,headers=headers)
print z.status_code
#返回200
#使用parsel中的Selector 来解析
sel = Selector(text=z.text)
print sel.xpath(‘//a[@class=”img x layer-view loaded”]/@href’)
#发现返回为空

这边为什么会返回空呢?不是应该返回所有链接的么?

我们可以查看下网页源代码,可以发现的内容都是通过js渲染上去的,所以我们才获取不到内容(这个可以用js2xml来解析,先放在这里,到详情页再来处理。)

所谓的异步加载

  1. 我们还是打开美女花瓣,陪你做生活的设计师(发现、采集你喜欢的美女图片)花瓣网(http://huaban.com/favorite/beauty/)
  2. 可以发现我们把页面拖动到最下面,会自动加载出新的内容(整个页面没有跳转,这就是所谓的异步加载。有些网页是需要手动点击“加载更多的”,原理都是一样的)
  3. 获取异步加载的请求
    1. “j0ga0has”第一个参数不知道是怎么回事,先放着
    2. “max”是 最上面的pin_id
    3. limit 是每次返回的条数
    4. 有人可能会问,你怎么知道这个参数是干嘛的?其实都是试出来的(或者说看出来的)
    5. 打开F12
    6. 拖动到页面最下面(有些网站是点击加载更多)
    7. 注意 我有勾选”xhr”
    8. 可以看到每次页面到最底部,都会发送一个请求。这个请求就是所谓的异步加载请求。
    1. 可以看到请求的参数如下: j0ga0has: max:1062527343 limit:20 wfl:1
    2. 如下图的pin_id,可以发现下一条请求的max就是上一条请求获取到的最后一个pin_id
    1. 我们查看返回值,发现竟然是json格式的,这样的话,都不需要我们解析了,那我们找找我们需要的链接地址在哪。
    1. 发现链接地址就是由pin_id拼接而成的,所以我们只要获取到这个pin_id就行。

用程序来实现:

url = ‘http://huaban.com/favorite/beauty/‘
params = { ‘j0ga0hbi’:’’, ‘max’:’1062161596’, ‘limit’:’100’, ‘wfl’:’1’}
z1 = requests.get(url=url,params=params,headers=headers)
print z1.status_code
#返回200
print z1.json()
#报错

然后发现竟然报错了。。。

为什么呢?我们查看请求的时候就是jsno格式的啊

我们打印下源代码看看

你会看到竟然是”<!DOCTYPE html><html “这样的,但是我们上面查看请求的时候,明明是如下图这样的啊

那么到底是哪里出了问题呢?

我们再次查看之前我们看到的异步请求

可以发现它有几个 特别的请求头

指定了格式为json ,那么我们加上去看看呢

Accept:application/json 
X-Request:JSON 
X-Requested-With:XMLHttpRequest
headers1 = { ‘User-Agent’:’Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36’, ‘Accept’:’application/json’, ‘X-Request’:’JSON’, ‘X-Requested-With’:’XMLHttpRequest’ } 
z2 = requests.get(url=url,params=params,headers=headers1) 
print z2.content

可以看到返回值和我们之前一样了。

获取pin_id

最后只要把pin_id拼接成url就可以了,如果你想要爬取所有的图片的话,那么你只需要把最后的pin_id 传入给max,再请求一次,直到pins为空为止

在上面我们已经获取到了所有的详情页的地址,那么我们现在只要获取到图片链接就行

  1. 随便打开一个详情页花瓣(http://huaban.com/pins/1062650100/)
  2. 查看图片地址
  1. 复制图片地址到网页源代码里面找找看
    1. 可以看到已经找到了,这边你也可以用正则表达式,来匹配所有的地址,但是太麻烦了,我们可以用js2xml
    1. 全部复制,发现没有找到
    1. 那么我们复制一部分

看代码.

就这样,我们已经把图片地址获取到了,只需要拼接下即可(记得去下重)

最后再次总结一下

看完本篇文章后,你应该要

  • 能知道如何抓取异步加载的请求
  • 了解js2xml的用法
  • 了解headers的用法

最后代码都在 kimg1234/pachong(https://github.com/kimg1234/pachong/blob/master/huaban%E7%88%AC%E8%99%AB.ipynb)

填一个坑,我在https://mp.weixin.qq.com/s?__biz=MzU2OTAxNTcwMw==&mid=100000023&idx=1&sn=0c0ff48e9bfca19dca6c4ed5bad46e0a&chksm=7c846def4bf3e4f9bde83bc8aa966419022c86dea5db9a00918f3b0220f9432c38f3b991d44a#rd

留下以下问题

其实解决方法也挺简单的,就是把content-type这一行注释掉。

那么为什么注释掉就可以了呢?请仔细研究研究http协议。。。

原文发布于微信公众号 - Python爬虫分享(python_crawler)

原文发表时间:2017-04-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏葡萄城控件技术团队

HTML5 & CSS3初学者指南(3) – HTML5新特性

介绍 本文介绍了 HTML5 的一些新特性。主要包含以下几个方面: Web 存储 地理位置 拖放 服务器发送事件 Web存储 HTML5...

2408
来自专栏carven

reactjs

最近在学习react js,ReactJS是Facebook开发的用于构建用户界面的JAVASCRIPT库,利用其可以实现组件式开发。

960
来自专栏腾讯NEXT学位

React 16 加载性能优化指南(上)

公司的新项目迁移到了 React 16 和 Webpack 4.0,写一篇文章来总结一下。

6535
来自专栏互联网高可用架构

通用架构师应该如何把控迁移技术方案

2426
来自专栏菩提树下的杨过

在win2008 r2中安装windows phone 7开发工具

默认情况下,windows phone7开发工具只能在windows7上安装,我的本本上好不容易把win2008 r2以及相关软件安装好,总不能因为这个又把wi...

1887
来自专栏地方网络工作室的专栏

打造前端 Deepin Linux 工作环境——安装配置 atom 编辑器

打造前端 Deepin Linux 工作环境——安装配置 atom 编辑器 好,我个人推荐大家使用 atom 编辑器,第一是免费,第二是好看,第三是好用。 安装...

4798
来自专栏菜鸟致敬

【菜鸟致敬】QQ坦白说解密

1.模拟手机QQ 首先使用浏览器来模拟手机qq 这里使用的 Chrome 谷歌浏览器 其他浏览器操作一致(绝大部分主流浏览器) 然后浏览器打开开发者工具完成...

1.4K12
来自专栏coding

django2实战4.创建文章列表页和详情页url适配自定义模型管理器在view中写业务逻辑新建模板文件添加分页功能

我们已经知道如何操作文章表的数据,接下来要将这些数据用界面显示出来。这就需要用到django的view层负责处理http请求,并将数据传给template模板进...

2133
来自专栏前端儿

既之前的基础,先写个简单的PHP 与数据库 的数据交流

现在先不用 css 和 javascript     先用纯 html  php  写吧。 所以那些 嵌入式 <font  size=....  什么的看看就算...

1202
来自专栏州的先生

Python爬虫实战入门四:使用Cookie模拟登录——获取电子书下载链接

1531

扫码关注云+社区

领取腾讯云代金券