Python爬虫实战

引言

  • 网络爬虫是抓取互联网信息的利器,成熟的开源爬虫框架主要集中于两种语言Java和Python。主流的开源爬虫框架包括:
1.分布式爬虫框架:Nutch
2.Java单机爬虫框架:Crawler4j, WebMagic, WebCollector、Heritrix
3.python单机爬虫框架:scrapy、pyspider
  • Nutch是专为搜索引擎设计的的分布式开源框架,上手难度高,开发复杂,基本无法满足快速开发的需要。
  • Java单机类爬虫框架普遍容易上手,最大的优势是在Java技术的生态圈非常完善,轮子很多,同一个功能的轮子都有好几个不同的厂家提供,对于搭建完整的系统或者整合到现有的Java系统中都较为容易。
  • 使用python开发的爬虫框架最大的特点是开发效率非常高,做相同的事情,代码量要远少于使用Java开发。缺点也比较明显,如果对python不熟悉的情况下,代码调试的时间会耗费掉编码时省下来的时间,甚至会浪费得更多,在爬取业务非常复杂的情况下,会花掉更多的调试时间。
  • 总结下各个爬虫框架的特点:
语言 插件 上手难度 支持分布式 支持JS页面抓取 特点
Nutch Java 支持,开发复杂 支持 不支持 专门为搜索引擎设计
Crawler4j Java 不支持 不支持 不支持 简单
WebMagic Java 支持 不支持 不支持 scrapy的Java版本
WebCollector Java 支持 不支持 支持 内置selenium
Heritrix Java 支持 不支持 不支持 扩展性较好
scrapy Java 支持 扩展可支持 不支持 扩展性强
pyspider Java 支持 支持 支持 强大的爬虫管理和监控
  • 所有的框架都解决了以下几个问题:
1. URL管理,URL去重
2. 多线程抓取,线程池管理
3. 代理
4. 指定cookie
5. 集成网页解析器
6. 广度遍历或者深度遍历抓取
  • 使用框架的最大好处是上述的问题都已经被解决,减少了开发的成本。缺点是开发模式受限于框架的设计思想,由于对框架的掌控程度有限,深度定制需要修改源码时会带来额外的成本。

python爬虫

  • 使用python编写爬虫具有非常明显的优势,当满足以下需求时,强烈建议首选python作为开发语言。
1. 减少开发量,并快速的看到结果
2. 垂直领域的精确抓取,具有明确的抓取对象,需要格式化抽取数据
3. 指定ajax请求抓取,或有抓取有限的url请求数据
4. 不作为持续集成的系统,仅需要快速收集数据

basic版爬虫

  • 在进行精确数据抓取时,使用框架并不一定具有优势。框架提供的主要功能:1.多线程抓取,2.URL管理和去重,3.增量抓取,4.监控。
    1. 多线程抓取的作用是提高抓取效率,但是现在主流的搜索平台,在关键数据上都做了防抓取的工作,过快的抓取频率很容易导致当前IP的流量被视为异常流量,最坏的结果是IP被列入网站的黑名单,被限流或禁止访问一段时间。
    2. 在进行精确数据抓取时,URL去重的作用并不大,甚至不需要。
    3. 增量抓取是个很实用的功能,对于大规模的数据抓取很有必要,因为在数据抓取的过程中很可能出现异常,或者某些原因需要暂停抓取过程,导致某些数据没有成功获取,增量抓取机制能够很好的支持在特殊情况下的数据抓取延续性。
    4. 监控,大型数据抓取系统必不可少的一个功能。
  • 很多爬虫框架并不直接支持增量抓取和监控功能,作为一个小范围的快速的精确数据抓取的爬虫,增量抓取和监控并不是必须的。
  • basic爬虫具有的基本功能:
    1. 发起http请求
    2. html解析
    3. json解析
  • 只要实现这三个功能,就能够写出一个从搜索平台上抓取数据的爬虫,在python的世界里,使用urllib2+BeautifulSoup+simplejson/json就能快速的实现一个爬虫。
  • 发起一个http登录请求:
import urllib2
import json
header = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36','Content-Type':'application/json'}
data = json.dumps({"userName":"wenbin", "password":"passwd"})
request = urllib2.Request(loginUrl, None, header)
response = urllib2.urlopen(request)
data = response.read()
response.close()
  • 有时需要保存cookie,或者携带cookie发送请求,将代码改造一下:
import urllib2
import json
import cookielib
header = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36','Content-Type':'application/json}
loginUrl = "${loginUrl}"
data = json.dumps({"userName":"wenbin", "password":"passwd"})
cookieFileName = 'cookie.txt'
# set cookie to request
cookie = cookielib.MozillaCookieJar(cookieFileName)
handler = urllib2.HTTPCookieProcessor(cookie)
opener = urllib2.build_opener(handler)
request = urllib2.Request(loginUrl, data, header)
response = opener.open(request)
# save the cookie
cookie.save(ignore_discard=True, ignore_expires=True)
response.close()
dataUrl = "${dataUrl}"
request = urllib2.Request(dataUrl, None, header)
data = response.read()
response.close()
  • cookie也可以从已有的文件中读取:
cookie = cookielib.MozillaCookieJar()
# get cookie from file
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
handler = urllib2.HTTPCookieProcessor(cookie)
opener = urllib2.build_opener(handler)
request = urllib2.Request(url, None, header)
response = opener.open(request)
data = response.read()
response.close()
  • BeautifulSoup解析html的demo
data = "

100

  • " # load html content soup = BeautifulSoup(data, "html.parser") # find the first

    with class=total fl totalCount = soup.find('h2', attrs={'class': 'total fl'}).span.contents[0] # find all
  • with class=clear xiaoquListItem xiaoquTag = soup.find_all("li", attrs={'class': 'clear xiaoquListItem'}) pageSize = len(xiaoquTag) for tag in xiaoquTag: # find all
    with class=title belong to tag titleSet = tag.findAll("div", attrs={'class': 'title'}) for title in titleSet: xiaoquUrl = title.a['href'] xiaoquId = str(xiaoquUrl).split('/')[4] xiaoquName = title.a.contents[0] xiaoquList.append([xiaoquId,xiaoquName,xiaoquUrl]) print xiaoquList
    • 在web 2.0的时代,许多数据是通过ajax请求的方式异步获取的,通常返回的数据为json格式,在许多情况下需要进行json解析, python提供了非常简单易用的json解析工具:json/simplejson,json和simplejson几乎是一样的,但simplejson在python 2.4以上的版本可以用,json在python 2.6以上版本可用
    import json
    jstr = '{"demoName":"demo","version":1}'
    jObject = json.loads(json_string)
    print jObject['version']
    object={"demoName":"demo","version":1,"cont":[1,2]}
    print json.dumps(object)
    • 使用urllib2+BeautifulSoup+simplejson/json编写的简易爬虫,能够实现对垂直类搜索平台的数据精确抓取和数据解析。

    爬虫进阶

    • basic版爬虫能够完成大部分的数据的抓取,但是仍然在一些情况下是无法抓取到目标数据的,比如当对方的数据是通过javascript对接口数据进行复杂的处理之后才输出的,那么直接抓取接口就无法获得正确的数据,而basic版的爬虫是无法运行javascript脚本的。
    • 为了能够正确运行javascript脚本,获取异步加载的、经过复杂处理之后才输出的数据,需要升级basic爬虫。在python体系下,推荐使用Selenium+PhantomJS+BeautifulSoup的组合实现新的爬虫。PhantomJS用来解析javascript和页面渲染,Selenium用来驱动PhantomJS,BeautifulSoup用来解析渲染结束后的html页面。
    • 在mac os下,使用PhantomJS发起请求,并使用BeautifulSoup解析渲染完成的html:
    from selenium import webdriver
    import os
    from bs4 import BeautifulSoup
    driverDir = "${dirvierDir}"
    os.environ["webdriver.phantomjs.driver"] = driverDir
    driver = webdriver.PhantomJS(driverDir)
    url = '${url}'
    driver.get(url)
    data = self.driver.page_source
    print data
    soup = BeautifulSoup(data, "html.parser")
    driver.close()
    • 其中,chromedriverDir为chrome浏览器的内核所在的文件目录。
    • selenium的webdriver还支持chrome、firefox和ie等浏览器,使用PhantomJS的原因是PhantomJS没有UI,因此运行速度更快,消耗的资源更少。进阶的爬虫具有更好的反爬虫能力,能够适应更多的场景。

    高级爬虫

    • 一个高级的爬虫,并不仅仅在于实现的技术、设计的理念有多先进,更在于其对被抓取的网站的服务器有多友好。无视服务器压力的爬虫一般会定义为低级的爬虫,把服务器拖垮,即影响了服务提供方的正常运营,也直接导致所需的数据无法获取。当然,肆无忌惮的爬虫也很容易被反爬虫程序发现,然后被封杀,或被‘投毒’。高级的爬虫需要具备以下几个特点:
    1. 控制对目标网站的抓取速度,如果仅仅是需要收集数据,而不要求数据的非常高的实时性,建议将访问频率控制到正常浏览的水平。
    2. 具有生命周期的管控,数据收集完成后,需要停止爬虫的工作。
    3. 健壮性,需要保证爬虫程序的健壮性,能够容忍坏的HTML、奇怪的服务器行为,不会因此而程序中断。
    4. 可扩展性,通用功能组件化,便于复用,也便于修改。
    5. 适当的监控,留下关键的抓取记录,便于异常恢复和抓取进度监控。
    6. 具有一定的‘反爬虫’抗性
    • 只要爬虫存在,‘反爬虫’就不会消失,做一个有礼貌的爬虫,将会极大的降低被‘反’的风险。

    小结&DEMO

    • 使用python能够非常快速、便捷的编写数据抓取的爬虫程序,能够满足大部分情况下的数据收集需求,带来无与伦比的快速反馈体验
    • 做一个有礼貌的爬虫,为了世界和平,请控制抓取速度
    • 真正的爬虫和反爬虫之战是RMB玩家的游戏,是技术和金钱的较量。
    • demo的github地址:https://github.com/huntertan/lstm-spider

    你可能感兴趣的:(爬虫,json,java)