Python爬虫 ---(1)爬虫基础知识

梁丘弘
2023-12-01

引言

  • 网络爬虫是抓取互联网信息的利器,成熟的开源爬虫框架主要集中于两种语言Java和Python。主流的开源爬虫框架包括:
1.分布式爬虫框架:Nutch
2.Java单机爬虫框架:Crawler4j, WebMagic, WebCollector、Heritrix
3.python单机爬虫框架:scrapy、pyspider
  • Nutch是专为搜索引擎设计的的分布式开源框架,上手难度高,开发复杂,基本无法满足快速开发的需要。
  • Java单机类爬虫框架普遍容易上手,最大的优势是在Java技术的生态圈非常完善,轮子很多,同一个功能的轮子都有好几个不同的厂家提供,对于搭建完整的系统或者整合到现有的Java系统中都较为容易。
  • 使用python开发的爬虫框架最大的特点是开发效率非常高,做相同的事情,代码量要远少于使用Java开发。缺点也比较明显,如果对python不熟悉的情况下,代码调试的时间会耗费掉编码时省下来的时间,甚至会浪费得更多,在爬取业务非常复杂的情况下,会花掉更多的调试时间。

  • 如果你想学习Python可以来这个群,首先是四七二,中间是三零九,最后是二六一,里面有大量的学习资料可以下载

  • 总结下各个爬虫框架的特点:

 语言插件上手难度支持分布式支持JS页面抓取特点
NutchJava支持,开发复杂支持不支持专门为搜索引擎设计
Crawler4jJava不支持不支持不支持简单
WebMagicJava支持不支持不支持scrapy的Java版本
WebCollectorJava支持不支持支持内置selenium
HeritrixJava支持不支持不支持扩展性较好
scrapyJava支持扩展可支持不支持扩展性强
pyspiderJava支持支持支持强大的爬虫管理和监控
  • 所有的框架都解决了以下几个问题:
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 = "<html><h2 class="total fl"><span>100</span></h2><lu><li class="clear xiaoquListItem"><div class="title"><a href="www.demo.com/1/2/3">高大上小区</a></div></li><li class="clear xiaoquListItem"><div class="title"><a href="www.demo.com/1/2/3">高大上小区</a></div></li><li class="clear xiaoquListItem"><div class="title"><a href="www.demo.com/1/2/3">高大上小区</a></div></li></lu></html>"
# load html content
soup = BeautifulSoup(data, "html.parser")
# find the first <h2> with class=total fl
totalCount = soup.find('h2', attrs={'class': 'total fl'}).span.contents[0]
# find all <li> with class=clear xiaoquListItem
xiaoquTag = soup.find_all("li", attrs={'class': 'clear xiaoquListItem'})
pageSize = len(xiaoquTag)
for tag in xiaoquTag:
# find all <div> 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玩家的游戏,是技术和金钱的较量。
 类似资料: