前言
我们的目标
了解爬虫
什么是爬虫
爬虫的基本流程
能爬取那些数据
如何解析数据
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)