从马蜂窝事件了解网络爬虫

前言
我们的目标
了解爬虫
什么是爬虫
爬虫的基本流程
能爬取那些数据
如何解析数据
python爬虫架构
Python 爬虫架构介绍
Scrapy介绍及框架图
具体爬虫操作
一、页面获取
二、目标提取
三、指定链接抓取
四、数据下载&存储
五、添加交互
附录
Py2.x vs Py3.x
爬虫脚本
从马蜂窝事件了解网络爬虫
前言
马蜂窝评论抄袭事件
从马蜂窝事件了解网络爬虫
经过数据分析,马蜂窝上有7454个抄袭账号,合计从携程、艺龙、美团、Agoda、Yelp上抄袭搬运了572万条餐饮点评与1221万条酒店点评。有1800万条是机器全网抓取的,各种评论截图拼凑在一起 ,简直触目惊心!
从马蜂窝事件了解网络爬虫

我们的目标
了解爬虫概念、流程、原理
首先肯定要实现图片抓取这个基本功能
然后实现对用户所给的链接进行抓取
最后可以有一定的简单交互

了解爬虫
什么是爬虫
举例来说:我们可以把互联网比作一张大的蜘蛛网,数据便是存放于蜘蛛网的各个节点,而爬虫就是一只小蜘蛛,沿着网络抓取自己的猎物(数据)。

从技术层面来说就是:通过程序模拟浏览器请求站点的行为,把站点返回的HTML代码/JSON数据/二进制数据(图片、视频) 爬到本地,进而提取自己需要的数据,存放起来使用。

爬虫的基本流程
模拟浏览器发送请求(获取网页代码)->提取有用的数据->存放于数据库或文件中
从马蜂窝事件了解网络爬虫

1、发起请求

使用http库向目标站点发起请求,即发送一个Request

Request包含:请求头、请求体等

Request模块缺陷:不能执行JS 和CSS 代码

2、获取响应内容

如果服务器能正常响应,则会得到一个Response

Response包含:html,json,图片,视频等

3、解析内容

解析html数据:正则表达式(RE模块),第三方解析库如Beautifulsoup,pyquery等

解析json数据:json模块

解析二进制数据:以wb的方式写入文件

4、保存数据

文本:纯文本,Json,Xml等

关系型数据库:如mysql,oracle,sql server等结构化数据库

非关系型数据库:MongoDB,Redis等key-value形式存储

能爬取那些数据
网页文本:如HTML文档,Json格式化文本等
图片:获取到的是二进制文件,保存为图片格式(妹子的图片...)
视频:同样是二进制文件(想看的视频...)
其他:只要你能通过浏览器访问的数据都可以通过爬虫获取(酒店信息....)

如何解析数据
直接处理
Json解析
正则表达式处理
BeautifulSoup解析处理
PyQuery解析处理
XPath解析处理
python爬虫架构
Python 爬虫架构介绍
爬虫架构主要由五个部分组成,分别是调度器、URL管理器、网页下载器、网页解析器、应用程序(爬取的有价值数据)。

调度器:相当于一台电脑的CPU,主要负责调度URL管理器、下载器、解析器之间的协调工作。
URL管理器:包括待爬取的URL地址和已爬取的URL地址,防止重复抓取URL和循环抓取URL,实现URL管理器主要用三种方式,通过内存、数据库、缓存数据库来实现。
网页下载器:通过传入一个URL地址来下载网页,将网页转换成一个字符串,网页下载器有urllib2(Python官方基础模块)包括需要登录、代理、和cookie,requests(第三方包)
网页解析器:将一个网页字符串进行解析,可以按照我们的要求来提取出我们有用的信息,也可以根据DOM树的解析方式来解析。

            常用的网页解析器有:

正则表达式(直观,将网页转成字符串通过模糊匹配的方式来提取有价值的信息,当文档比较复杂的时候,该方法提取数据的时候就会非常的困难)
html.parser(Python自带的)
beautifulsoup(第三方插件,html.parser 和 beautifulsoup 以及 lxml 都是以 DOM 树的方式进行解析的)
lxml(第三方插件,可以解析 xml 和 HTML)
应用程序:就是从网页中提取的有用数据组成的一个应用。
下面用一个图来解释一下调度器是如何协调工作的:
从马蜂窝事件了解网络爬虫

我们来看一下主流爬虫框架在GitHub上的活跃度:
从马蜂窝事件了解网络爬虫

Scrapy介绍及框架图
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。Scrapy 使用 Twisted这个异步网络库来处理网络通讯,架构清晰,并且包含了各种中间件接口,可以灵活的完成各种需求。

具体爬虫操作
我们以百度贴吧为例,一步步教你如何进行图片爬取。

一、页面获取
寻找规律,分析规律

图中的黑色方框左边填写xpth,右边会返回对应的结果,可以看到当前页面的帖子全部抓取到了。xpth具体怎么写要根据右边的检查元素来具体分析,每个网站的方式不一样,但是细心寻找可以找到相同的规律。

从马蜂窝事件了解网络爬虫

二、目标提取
找到规律并能匹配上开始写代码了:go

要让python可以进行对网页的访问,那肯定要用到urllib.request包

urllib中有 urlopen(str) 方法用于打开网页并返回一个对象,调用这个对象的read()方法后能直接获得网页的源代码,内容与浏览器右键查看源码的内容一样。
从马蜂窝事件了解网络爬虫

三、指定链接抓取
分析当前页面所有的贴吧名,即:/p/xxxxxxx

之后拼接 “host + 贴吧名”,行程最终的贴吧链接
从马蜂窝事件了解网络爬虫

进入每个帖子后,再对帖子内的图片进行一次过滤,仅匹配与楼主上传的相关图片
从马蜂窝事件了解网络爬虫

四、数据下载&存储
爬取贴吧前多少页的数据
从马蜂窝事件了解网络爬虫
从马蜂窝事件了解网络爬虫

五、添加交互
从马蜂窝事件了解网络爬虫

附录
Py2.x vs Py3.x
Py2.x:Urllib库、Urllin2库

Py3.x:Urllib库

变化:

2.x vs 3.x

在Pytho2.x中使用import urllib2——-对应的,在Python3.x中会使用import urllib.request,urllib.error。
在Pytho2.x中使用import urllib——-对应的,在Python3.x中会使用import urllib.request,urllib.error,urllib.parse。
在Pytho2.x中使用import urlparse——-对应的,在Python3.x中会使用import urllib.parse。
在Pytho2.x中使用import urlopen——-对应的,在Python3.x中会使用import urllib.request.urlopen。
在Pytho2.x中使用import urlencode——-对应的,在Python3.x中会使用import urllib.parse.urlencode。
在Pytho2.x中使用import urllib.quote——-对应的,在Python3.x中会使用import urllib.request.quote。
在Pytho2.x中使用cookielib.CookieJar——-对应的,在Python3.x中会使用http.CookieJar。
在Pytho2.x中使用urllib2.Request——-对应的,在Python3.x中会使用urllib.request.Request。

爬虫脚本
爬取百度贴吧贴主的图片

-- coding:utf-8 --

import urllib.request
from lxml import etree

def loadPage(url):
"""

作用:根据url发送请求,获取服务器响应文件
url: 需要爬取的url地址

"""
# headers = {"User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}

request = urllib.request.Request(url)
html = urllib.request.urlopen(request).read()
# 解析HTML文档为HTML DOM模型
content = etree.HTML(html)
# print content
# 返回所有匹配成功的列表集合
link_list = content.xpath('//div[@class="t_con cleafix"]/div/div/div/a/@href')

# link_list = content.xpath('//a[@class="j_th_tit"]/@href')
for link in link_list:

  fulllink = "http://tieba.baidu.com" + link
  # 组合为每个帖子的链接
  # print link
  loadImage(fulllink)

取出每个帖子里的每个图片连接

def loadImage(link):
headers = {

  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

request = urllib.request.Request(link, headers=headers)
html = urllib.request.urlopen(request).read()
# 解析
content = etree.HTML(html)
# 取出帖子里每层层主发送的图片连接集合
# link_list = content.xpath('//img[@class="BDE_Image"]/@src')
# link_list = content.xpath('//div[@class="post_bubble_middle"]')
link_list = content.xpath('//img[@class="BDE_Image"]/@src')
# 取出每个图片的连接
for link in link_list:

  print("link:" + link)
  writeImage(link)

def writeImage(link):
"""

作用:将html内容写入到本地
link:图片连接

"""
# print "正在保存 " + filename
headers = {

  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# 文件写入
request = urllib.request.Request(link, headers=headers)
# 图片原始数据
image = urllib.request.urlopen(request).read()
# 取出连接后10位做为文件名
filename = link[-10:]
# 写入到本地磁盘文件内
with open("/Users/didi/Downloads/crawlertest/" + filename, "wb") as f:

  f.write(image)

# print("已经成功下载 " + filename)

def tiebaSpider(url, beginPage, endPage):
"""

作用:贴吧爬虫调度器,负责组合处理每个页面的url
url : 贴吧url的前部分
beginPage : 起始页
endPage : 结束页

"""
for page in range(beginPage, endPage + 1):

  pn = (page - 1) * 50
  filename = "第" + str(page) + "页.html"
  print(filename)
  fullurl = url + "&pn=" + str(pn)
  print(fullurl)
  loadPage(fullurl)
  # print html
   
  print("下载完成")

if name == "__main__":
kw = input("请输入需要爬取的贴吧名:")
beginPage = int(input("请输入起始页:"))
endPage = int(input("请输入结束页:"))

url = "http://tieba.baidu.com/f?"
key = urllib.parse.urlencode({"kw": kw})
fullurl = url + key
tiebaSpider(fullurl, beginPage, endPage)

上一篇:前端工程师必备技能汇总


下一篇:MongoDB系列 | 集合的基本操作