爬虫概述
网络蜘蛛(Web spider)也叫网络爬虫(Web crawler),蚂蚁(ant),自动检索工具(automatic indexer),或者(在FOAF软件概念中)网络疾走(WEB scutter),是一种“自动化浏览网络”的程序,或者说是一种网络机器人。它们被广泛用于互联网搜索引擎或其他类似网站,以获取或更新这些网站的内容和检索方式。它们可以自动采集所有其能够访问到的页面内容,以供搜索引擎做进一步处理(分检整理下载的页面),而使得用户能更快的检索到他们需要的信息。
使用爬虫抓取网页
想要使用python抓取网页,首先出场的就是urllib2,使用其urlopen
方法就可以获取到一个网页信息
1 | import urllib2 |
对于urllib2库中的urlopen()方法,它可以接受三个参数urlopen(url,data,timeout)
url即为URL,data为访问URL时要传送的数据,timeout为超时时间。后两个参数可以不添加,data默认为空None,timeout默认为socket._GLOBAL_DEFAULT_TIMEOUT
通过urlopen方法获得的信息保存到response中
通过打印response.read()可以获取网页内容
第三的参数就是timeout设置
response = urllib2.urlopen('http://sdfsdf',timeout=10)
response = urllib2.urlopen('http://sdfsdf',data,10)
Request对象
在urlopen的参数中,可以传入一个request请求,我们可以创建一个Request的实例来作为参数传给urlopen
1 | import urllib2 |
Post请求与Get请求
POST
1 | import urllib |
还可以使用以下方式定义字典
1 | values = {} |
GET
1 | ... |
Urllib库用法
设置Headers
在Headers里有很多的信息,如文件编码,压缩方式,请求身份等
user_agent就是请求身份'User_Agent':'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
这样就设置好了一个headers,在构建request时传入,这样在请求页面是,就会与request一起发到服务器上。
另外,有的服务器设置了防盗链,服务器会识别headers中的referer是不是它自己,如果不是,服务器就不会响应请求。'Referer':'http://urlurlurl'
另外,在headers中还有一些其他属性
User-Agent : 有些服务器或 Proxy 会通过该值来判断是否是浏览器发出的请求
Content-Type : 在使用 REST 接口时,服务器会检查该值,用来确定 HTTP Body 中的内容该怎样解析。
application/xml : 在 XML RPC,如 RESTful/SOAP 调用时使用
application/json : 在 JSON RPC 调用时使用
application/x-www-form-urlencoded : 浏览器提交 Web 表单时使用
在使用服务器提供的 RESTful 或 SOAP 服务时, Content-Type 设置错误会导致服务器拒绝服务
Proxy设置
urllib2默认会使用环境变量http_proxy设置HTTP Proxy.有些网站会检测某一段时间内某个IP的访问次数,如果访问次数过多,会禁止访问。所以可以通过设置一些代理服务器来协助你抓取页面。
Proxy的用法
1 | import urllib2 |
HTTP的PUT和DELETE方法
PUT和POST极为相似,都是向服务器发送数据,但它们之间有一个重要区别,PUT通常指定了资源的存放位置,而POST则没有,POST的数据存放位置由服务器自己决定。
DELETE:删除某一个资源。很少用到。
1 | import urllib2 |
URLError异常处理
URLError
要想在python中捕获异常,就要用到try-except语句
1 | import urllib2 |
HTTPError
HTTPError是URLError的子类,HTTPError实例产生后,会有一个code属性。
code属性是服务器返回的状态码
由于HTTPError的父类是URLError,因此父类的异常应该放在子类的后面
1 | import urllib2 |
如果捕获到了HTTPError,则输出code,不会再处理URLError异常。如果发生的不是HTTPError,则会去捕获URLError异常,输出错误原因。
另外还可以加入 hasattr属性提前对属性进行判断
1 | import urllib2 |
Cookie的使用
Opener
当你获取一个URL你使用一个opener(一个urllib2.OpenerDirector的实例)。在前面,我们都是使用的默认的opener,也就是urlopen。它是一个特殊的opener,可以理解成opener的一个特殊实例,传入的参数仅仅是url,data,timeout。
如果我们需要用到Cookie,只用这个opener是不能达到目的的,所以我们需要创建更一般的opener来实现对Cookie的设置。
Cookielib
cookielib模块的主要作用是提供可存储cookie的对象,以便于与urllib2模块配合使用来访问Internet资源。
可以利用本模块的CookieJar类的对象来捕获cookie并在后续连接请求时重新发送,比如可以实现模拟登录功能。该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。
CookieJar —-派生—->FileCookieJar —-派生—–>MozillaCookieJar和LWPCookieJar
获取Cookie保存到变量
1 | import urllib2 |
打印结果
1 | Name=BAIDUID |
保存Cookie到文件
1 | # -*- coding: utf-8 -*- |
ignore_discard的意思是即使cookies将被丢弃也将它保存下来,ignore_expires的意思是如果在该文件中cookies已经存在,则覆盖原文件写入,在这里,我们将这两个全部设置为True。运行之后,cookies将被保存到cookie.txt文件中
从文件中获取Cookie并访问
1 | # -*- coding: utf-8 -*- |
利用Cookie模拟网站登录
利用cookie模拟网站登录学校教务系统,读取课表
1 | # -*- coding: utf-8 -*- |
正则表达式
正则表达式注解
贪婪模式与非贪婪模式
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式”ab”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量词”ab?”,将找到”a”。
常用非贪婪模式提取
反斜杠
使用反斜杠作为转义字符
python中可以使用r代替\
在正则表达式中如果要匹配”",需要写成\\,使用r可以写成r” \“表示。匹配使用可以写成\d,r” \d”
python Re模块
1 | #返回pattern对象 |
pattern = re.compile(r'hello')
在参数中我们传入了原生字符串对象,通过compile方法编译生成一个pattern对象,然后我们利用这个对象来进行进一步的匹配
参数flag是匹配模式,取值可以使用按位或运算符’|’表示同时生效,比如re.I|re.M
。
1 | re.I(全拼:IGNORECASE): 忽略大小写(括号内是完整写法,下同) |
re.match(pattern, string[, flags])
这个方法将会从string(我们要匹配的字符串)的开头开始,尝试匹配pattern,一直向后匹配,如果遇到无法匹配的字符,立即返回None,如果匹配未结束已经到达string的末尾,也会返回None。两个结果均表示匹配失败,否则匹配pattern成功,同时匹配终止,不再对string向后匹配
match对象的的属性和方法
result.group , result.string
- string: 匹配时使用的文本。
- re: 匹配时使用的Pattern对象。
- pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
- endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
- lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
- lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:
- group([group1, …]):
获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。 - groups([default]):
以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。 - groupdict([default]):
返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。 - start([group]):
返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。 - end([group]):
返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。 - span([group]):
返回(start(group), end(group))。 - expand(template):
将匹配到的分组代入template中然后返回。template中可以使用\id或\g、\g引用分组,但不能使用编号0。\id与\g是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符’0’,只能使用\g0。
re.search(pattern, string[, flags])
search方法与match方法极其类似,区别在于match()函数只检测re是不是在string的开始位置匹配,search()会扫描整个string查找匹配,match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回None。同样,search方法的返回对象同样match()返回对象的方法和属性
re.split(pattern, string[, maxsplit])
按照能够匹配的子串将string分割后返回列表。maxsplit用于指定最大分割次数,不指定将全部分割
1 | import re |
re.findall(pattern, string[, flags])
搜索string,以列表形式返回全部能匹配的子串
1 | import re |
re.finditer(pattern, string[, flags])
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器
1 | import re |
re.sub(pattern, repl, string[, count])
使用repl替换string中每一个匹配的子串后返回替换后的字符串。
当repl是一个字符串时,可以使用\id或\g、\g引用分组,但不能使用编号0
当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
count用于指定最多替换次数,不指定时全部替换
1 | import re |
re.subn(pattern, repl, string[, count])
返回 (sub(repl, string[, count]), 替换次数)
1 | import re |