爬虫
1、爬虫的实际例子:
搜索引擎(百度、谷歌、360搜索等)。 伯乐在线。 惠惠购物助手。 数据分析与研究(数据冰山知乎专栏)。 抢票软件等。
2、什么是网络爬虫:
通俗理解:爬虫是一个模拟人类请求网站行为的程序。可以自动请求网页、并数据抓取下来,然后使用一定的规则提取有价值的数据。 专业介绍:网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
3、通用爬虫和聚焦爬虫:
通用爬虫:通用爬虫是搜索引擎抓取系统(百度、谷歌、搜狗等)的重要组成部分。主要是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份。 聚焦爬虫:是面向特定需求的一种网络爬虫程序,他与通用爬虫的区别在于:聚焦爬虫在实施网页抓取的时候会对内容进行筛选和处理,尽量保证只抓取与需求相关的网页信息。
4、什么是http和https协议:
HTTP协议:全称是HyperText Transfer Protocol,中文意思是超文本传输协议,是一种发布和接收HTML页面的方法。服务器端口号是80端口。 HTTPS协议:是HTTP协议的加密版本,在HTTP下加入了SSL层。服务器端口号是443端口。
5、在浏览器中发送一个http请求的过程:
当用户在浏览器的地址栏中输入一个URL并按回车键之后,浏览器会向HTTP服务器发送HTTP请求。HTTP请求主要分为“Get”和“Post”两种方法。 当我们在浏览器输入URL http://www.baidu.com 的时候,浏览器发送一个Request请求去获取 http://www.baidu.com 的html文件,服务器把Response文件对象发送回给浏览器。 浏览器分析Response中的 HTML,发现其中引用了很多其他文件,比如Images文件,CSS文件,JS文件。 浏览器会自动再次发送Request去获取图片,CSS文件,或者JS文件。 当所有的文件都下载成功后,网页会根据HTML语法结构,完整的显示出来了。
6、url详解:
URL是Uniform Resource Locator的简写,统一资源定位符。 一个URL由以下几部分组成:
scheme://host:port/path/?query-string=xxx#anchor
scheme:代表的是访问的协议,一般为http或者https以及ftp等。 host:主机名,域名,比如www.baidu.com。 port:端口号。当你访问一个网站的时候,浏览器默认使用80端口。 path:查找路径。比如:www.jianshu.com/trending/now,后面的trending/now就是path。 query-string:查询字符串,比如:www.baidu.com/s?wd=python,后面的wd=python就是查询字符串。 anchor:锚点,后台一般不用管,前端用来做页面定位的。
在浏览器中请求一个url,浏览器会对这个url进行一个编码。除英文字母,数字和部分符号外,其他的全部使用百分号+十六进制码值进行编码。
7、常用的请求方法:
在Http协议中,定义了八种请求方法。这里介绍两种常用的请求方法,分别是get请求和post请求。
get请求:一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用get请求。 post请求:向服务器发送数据(登录)、上传文件等,会对服务器资源产生影响的时候会使用post请求。 以上是在网站开发中常用的两种方法。并且一般情况下都会遵循使用的原则。但是有的网站和服务器为了做反爬虫机制,也经常会不按常理出牌,有可能一个应该使用get方法的请求就一定要改成post请求,这个要视情况而定。
8、请求头常见参数:
在http协议中,向服务器发送一个请求,数据分为三部分,第一个是把数据放在url中,第二个是把数据放在body中(在post请求中),第三个就是把数据放在head中。这里介绍在网络爬虫中经常会用到的一些请求头参数:
User-Agent:浏览器名称。这个在网络爬虫中经常会被使用到。请求一个网页的时候,服务器通过这个参数就可以知道这个请求是由哪种浏览器发送的。如果我们是通过爬虫发送请求,那么我们的User-Agent就是Python,这对于那些有反爬虫机制的网站来说,可以轻易的判断你这个请求是爬虫。因此我们要经常设置这个值为一些浏览器的值,来伪装我们的爬虫。 Referer:表明当前这个请求是从哪个url过来的。这个一般也可以用来做反爬虫技术。如果不是从指定页面过来的,那么就不做相关的响应。 Cookie:http协议是无状态的。也就是同一个人发送了两次请求,服务器没有能力知道这两个请求是否来自同一个人。因此这时候就用cookie来做标识。一般如果想要做登录后才能访问的网站,那么就需要发送cookie信息了。
9、常见响应状态码:
200:请求正常,服务器正常的返回数据。 301:永久重定向。比如在访问www.jingdong.com 的时候会重定向到 www.jd.com。 302:临时重定向。比如在访问一个需要登录的页面的时候,而此时没有登录,那么就会重定向到登录页面。 400:请求的url在服务器上找不到。换句话说就是请求url错误。 403:服务器拒绝访问,权限不够。 500:服务器内部错误。可能是服务器出现bug了。
10、urllib库
(1)urllib库是Python中一个最基本的网络请求库。可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。
(2)urlopen函数:在Python3的urllib库中,所有和网络请求相关的方法,都被集到urllib.request模块下面了,以先来看下urlopen函数基本的使用:
from urllib import request
resp = request. urlopen( 'http://www.baidu.com' )
print ( resp. read( ) )
实际上,使用浏览器访问百度,右键查看源代码。你会发现,跟我们刚才打印出来的数据是一模一样的。也就是说,上面的三行代码就已经帮我们把百度的首页的全部代码爬下来了。一个基本的url请求对应的python代码真的非常简单。
以下对urlopen函数的进行详细讲解:
1、url:请求的url。
2、data:请求的data,如果设置了这个值,那么将变成post请求。
3、返回值:返回值是一个http.client.HTTPResponse对象,这个对象是一个类文件句柄对象。有read(size)、readline、readlines以及getcode等方法。
(3)urlretrieve函数:
这个函数可以方便的将网页上的一个文件保存到本地。以下代码可以非常方便的将百度的首页下载到本地:
from urllib import request
request. urlretrieve( 'http://www.baidu.com/' , 'baidu.html' )
(4)urlencode函数:
用浏览器发送请求的时候,如果url中包含了中文或者其他特殊字符,那么浏览器会自动的给我们进行编码。而如果使用代码发送请求,那么就必须手动的进行编码,这时候就应该使用urlencode函数来实现。urlencode可以把字典数据转换为URL编码的数据。示例代码如下:
from urllib import parse
data = { 'name' : '爬虫基础' , 'greet' : 'hello world' , 'age' : 100 }
qs = parse. urlencode( data)
print ( qs)
(5)parse_qs函数:
可以将经过编码后的url参数进行解码。示例代码如下:
from urllib import parse
qs = "name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100"
print ( parse. parse_qs( qs) )
(6)urlparse和urlsplit:有时候拿到一个url,想要对这个url中的各个组成部分进行分割,那么这时候就可以使用urlparse或者是urlsplit来进行分割。示例代码如下:
from urllib import request, parse
url = 'http://www.baidu.com/s?username=zhiliao'
result = parse. urlsplit( url)
print ( 'scheme:' , result. scheme)
print ( 'netloc:' , result. netloc)
print ( 'path:' , result. path)
print ( 'query:' , result. query)
urlparse和urlsplit基本上是一模一样的。唯一不一样的地方是,urlparse里面多了一个params属性,而urlsplit没有这个params属性。比如有一个url为:url = 'http://www.baidu.com/s;hello?wd=python&username=abc#1 ',那么urlparse可以获取到hello,而urlsplit不可以获取到。url中的params也用得比较少。
(7)request.Request类:如果想要在请求的时候增加一些请求头,那么就必须使用request.Request类来实现。比如要增加一个User-Agent,示例代码如下:
from urllib import request
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
req = request. Request( "http://www.baidu.com/" , headers= headers)
resp = request. urlopen( req)
print ( resp. read( ) )
(8)ProxyHandler处理器(代理设置)
很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。urllib中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:
from urllib import request
handler = request. ProxyHandler( { "http" : "218.66.161.88:31769" } )
opener = request. build_opener( handler)
req = request. Request( "http://httpbin.org/ip" )
resp = opener. open ( req)
print ( resp. read( ) )
11、cookie:
在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie只能存储一些小量的数据。
cookie的格式:Set-Cookie: NAME=VALUE;Expires/Max-age=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE
参数意义:
NAME:cookie的名字。
VALUE:cookie的值。
Expires:cookie的过期时间。
Path:cookie作用的路径。
Domain:cookie作用的域名。
SECURE:是否只在https协议下起作用。
使用cookielib库和HTTPCookieProcessor模拟登录:
Cookie 是指网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。这里以人人网为例。人人网中,要访问某个人的主页,必须先登录才能访问,登录说白了就是要有cookie信息。那么如果我们想要用代码的方式访问,就必须要有正确的cookie信息才能访问。解决方案有两种,第一种是使用浏览器访问,然后将cookie信息复制下来,放到headers中。示例代码如下:
from urllib import request
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36' ,
'Cookie' : 'anonymid=jacdwz2x-8bjldx; depovince=GW; _r01_=1; _ga=GA1.2.1455063316.1511436360; _gid=GA1.2.862627163.1511436360; wp=1; JSESSIONID=abczwY8ecd4xz8RJcyP-v; jebecookies=d4497791-9d41-4269-9e2b-3858d4989785|||||; ick_login=884e75d4-f361-4cff-94bb-81fe6c42b220; _de=EA5778F44555C091303554EBBEB4676C696BF75400CE19CC; p=61a3c7d0d4b2d1e991095353f83fa2141; first_login_flag=1; ln_uact=970138074@qq.com; ln_hurl=http://hdn.xnimg.cn/photos/hdn121/20170428/1700/main_nhiB_aebd0000854a1986.jpg; t=3dd84a3117737e819dd2c32f1cdb91d01; societyguester=3dd84a3117737e819dd2c32f1cdb91d01; id=443362311; xnsid=169efdc0; loginfrom=syshome; ch_id=10016; jebe_key=9c062f5a-4335-4a91-bf7a-970f8b86a64e%7Ca022c303305d1b2ab6b5089643e4b5de%7C1511449232839%7C1; wp_fold=0'
}
url = 'http://www.renren.com/880151247/profile'
req = request. Request( url, headers= headers)
resp = request. urlopen( req)
with open ( 'renren.html' , 'w' ) as fp:
fp. write( resp. read( ) . decode( 'utf-8' ) )
但是每次在访问需要cookie的页面都要从浏览器中复制cookie比较麻烦。在Python处理Cookie,一般是通过http.cookiejar模块和urllib模块的HTTPCookieProcessor处理器类一起使用。http.cookiejar模块主要作用是提供用于存储cookie的对象。而HTTPCookieProcessor处理器主要作用是处理这些cookie对象,并构建handler对象。
http.cookiejar模块:
该模块主要的类有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。这四个类的作用分别如下:
(1)CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。
(2)FileCookieJar (filename,delayload=None,policy=None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。
(3)MozillaCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生而来,创建与Mozilla浏览器 cookies.txt兼容的FileCookieJar实例。
(4)LWPCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生而来,创建与libwww-perl标准的 Set-Cookie3 文件格式兼容的FileCookieJar实例。
登录人人网:利用http.cookiejar和request.HTTPCookieProcessor登录人人网。相关示例代码如下:
from urllib import request, parse
from http. cookiejar import CookieJar
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
def get_opener ( ) :
cookiejar = CookieJar( )
handler = request. HTTPCookieProcessor( cookiejar)
opener = request. build_opener( handler)
return opener
def login_renren ( opener) :
data = { "email" : "970138074@qq.com" , "password" : "pythonspider" }
data = parse. urlencode( data) . encode( 'utf-8' )
login_url = "http://www.renren.com/PLogin.do"
req = request. Request( login_url, headers= headers, data= data)
opener. open ( req)
def visit_profile ( opener) :
url = 'http://www.renren.com/880151247/profile'
req = request. Request( url, headers= headers)
resp = opener. open ( req)
with open ( 'renren.html' , 'w' ) as fp:
fp. write( resp. read( ) . decode( "utf-8" ) )
if __name__ == '__main__' :
opener = get_opener( )
login_renren( opener)
visit_profile( opener)
保存cookie到本地:保存cookie到本地,可以使用cookiejar的save方法,并且需要指定一个文件名:
from urllib import request
from http. cookiejar import MozillaCookieJar
cookiejar = MozillaCookieJar( "cookie.txt" )
handler = request. HTTPCookieProcessor( cookiejar)
opener = request. build_opener( handler)
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
req = request. Request( 'http://httpbin.org/cookies' , headers= headers)
resp = opener. open ( req)
print ( resp. read( ) )
cookiejar. save( ignore_discard= True , ignore_expires= True )
从本地加载cookie:从本地加载cookie,需要使用cookiejar的load方法,并且也需要指定方法:
from urllib import request
from http. cookiejar import MozillaCookieJar
cookiejar = MozillaCookieJar( "cookie.txt" )
cookiejar. load( ignore_expires= True , ignore_discard= True )
handler = request. HTTPCookieProcessor( cookiejar)
opener = request. build_opener( handler)
headers = {
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'
}
req = request. Request( 'http://httpbin.org/cookies' , headers= headers)
resp = opener. open ( req)
print ( resp. read( ) )