UDN-企业互联网技术人气社区

板块导航

浏览  : 4683
回复  : 1

[python] Python爬虫爬取动态页面思路+实例(一)

[复制链接]
葡萄柚的头像 楼主
  有时候,我们天真无邪的使用urllib库或Scrapy下载HTML网页时会发现,我们要提取的网页元素并不在我们下载到的HTML之中,尽管它们在浏览器里看起来唾手可得。

  这说明我们想要的元素是在我们的某些操作下通过js事件动态生成的。举个例子,我们在刷QQ空间或者微博评论的时候,一直往下刷,网页越来越长,内容越来越多,就是这个让人又爱又恨的动态加载。

  爬取动态页面目前来说有两种方法

  分析页面请求(这篇介绍这个)

  selenium模拟浏览器行为(霸王硬上弓,以后再说)

  言归正传,下面介绍一下通过分析页面请求的方法爬取动态加载页面的思路。 中心思想 就是找到那个发请求的JavaScript文件。

  举两个例子,京东评论和上证股票。

  京东评论

  这是一个比较简单的例子。

  首先我们随便找一个热卖的商品,评论比较多。

  就这个吧 威刚(ADATA) SU800 256G 3D NAND SATA3固态硬盘 。

  点进去看看这个页面现在的状况
8.png

  滚动条给的第一印象感觉这页仿佛没多少内容。

  键盘F12打开开发者工具,选择Network选项卡,选择JS,如下图
7.png

  然后,我们来拖动右侧的滚动条,这时就会发现,开发者工具里出现了新的js请求(还挺多的),不过草草翻译一下,很容易就能看出来哪个是取评论的,如下图
6.png

  好,复制出 js请求的目标url
5.png

  在浏览器中打开,发现我们想要的数据就在这里,如下图
4.png

  这整个页面是一个json格式的数据,对于京东来说,当用户下拉页面时,触发一个js事件,向服务器发送上面的请求取数据,然后通过一定的js逻辑把取到的这些json数据填充到HTML页面当中。对于我们Spider来说,我们要做的就是把这些json数据整理提取。

  在实际应用中,当然我们不可能去每个页面里找出来这个js发起的请求目标地址,所以我们需要分析这个请求地址的规律,一般情况下规律是比较好找的,因为规律太复杂服务方维护也难。那我们就来看一下京东这个请求:

  https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv337&productId=3311073&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0

  挺长的一个GET请求,不过参数命名都很规范,产品ID,评论页码什么的,因为我这里只是举个例子,我就不一个一个去研究了~

  思路有了,就按照正常的爬虫去写就好了,发请求,得到响应,解析数据,后续处理等等……

  上证股票

  这是前段时间一位道友问我的一个问题,感觉还是挺有嚼头的,比上例要难。

  目标网址: 上海证券交易所

  目的是把每一页的股票信息都得到,看似很简单,但是通过查看源代码发现,每一页的链接在源代码里是看不到的。如下图
3.png

  ok,又是js动态加载,在源代码里不显示,不过一定躲不过我们的开发者工具,按照上面京东的思路,切到Network、js选项卡,点击页码,获得请求地址,一切行云流水,如下图
2.png

  然而,当我们复制出这个url,在浏览器中打开的时候,浏览器呈现的信息却是:
1.png

  403错误!奇哉怪也!

  究其原因,403状态码什么意思呢?意思就是说,本服务器知道你发来这一串url想找啥呢,但是老子就不给你!

  怎么办,有办法~

  想想看,为什么我们在那个页面上点击第二页第三页的时候能够正常的获取到数据?为什么我们直接请求不行?都是同一个浏览器呀。

  问题就在于,浏览器通过上一个页面发起的请求和单独发的请求,头信息(request header)是不同的,比方说cookie、refer这些字段,服务器就通过这些就把我们的请求过滤掉了。

  浏览器如此,我们的爬虫也是如此,最后我解决这个问题的方法是给爬虫设定详细的请求头(从我们能请求到的原始页获得),包括cookie,refer等,终于成功的得到了返回的json数据。

  这份代码是用python3的urllib写的,我只帮他写了取一页的数据,逻辑他自己去写了。如下,看官不妨试试将头信息去掉~
  1. import urllib.request

  2. Cookie = "PHPStat_First_Time_10000011=1480428327337; PHPStat_Cookie_Global_User_Id=_ck16112922052713449617789740328; PHPStat_Return_Time_10000011=1480428327337; PHPStat_Main_Website_10000011=_ck16112922052713449617789740328%7C10000011%7C%7C%7C; VISITED_COMPANY_CODE=%5B%22600064%22%5D; VISITED_STOCK_CODE=%5B%22600064%22%5D; seecookie=%5B600064%5D%3A%u5357%u4EAC%u9AD8%u79D1; _trs_uv=ke6m_532_iw3ksw7h; VISITED_MENU=%5B%228451%22%2C%229055%22%2C%229062%22%2C%229729%22%2C%228528%22%5D"

  3. url = "http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback41883&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=3&pageHelp.pageSize=25&pageHelp.pageNo=3&pageHelp.endPage=31&_=1480431103024"

  4. headers = {
  5.     'User-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36',
  6.     'Cookie': Cookie,
  7.     'Connection': 'keep-alive',
  8.     'Accept': '*/*',
  9.     'Accept-Encoding': 'gzip, deflate, sdch',
  10.     'Accept-Language': 'zh-CN,zh;q=0.8',
  11.     'Host': 'query.sse.com.cn',
  12.     'Referer': 'http://www.sse.com.cn/assortment/stock/list/share/'
  13. }

  14. req = urllib.request.Request(url,None,headers)
  15. response = urllib.request.urlopen(req)
  16. the_page = response.read()
  17. print(the_page.decode("utf8"))
复制代码

  结语

  还是那句话,通过分析页面请求的方法爬取动态加载页面的思路。 中心思想 就是找到那个发请求的JavaScript文件。然后利用我们既有的爬虫知识去构造请求就可以了。

相关帖子

发表于 2016-12-23 15:49:08 | 显示全部楼层
学习
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部