爬虫基础
一.爬虫入门
1.爬虫是什么?
爬虫:一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。
2.爬虫原理
-
获取初始的URL。初始的URL地址可以由用户人为地指定,也可以由用户指定的某个或某几个初始爬取网页决定。
-
根据初始的URL爬取页面并获得新的URL。获得初始的URL地址之后,首先需要爬取对应URL地址中的网页,爬取了对应的URL地址中的网页后,将网页存储到原始数据库中,并且在爬取网页的同时,发现新的URL地址,同时将已爬取的URL地址存放到一个URL列表中,用于去重及判断爬取的进程。
-
将新的URL放到URL队列中。在第2步中,获取了下一个新的URL地址之后,会将新的URL地址放到URL队列中。
-
从URL队列中读取新的URL,并依据新的URL爬取网页,同时从新网页中获取新URL,并重复上述的爬取过程。
-
满足爬虫系统设置的停止条件时,停止爬取。在编写爬虫的时候,一般会设置相应的停止条件。如果没有设置停止条件,爬虫则会一直爬取下去,一直到无法获取新的URL地址为止,若设置了停止条件,爬虫则会在停止条件满足时停止爬取。
3.第一个爬虫程序
#导包 import urllib.request #定义url url = "http://www.baidu.com" #指定url req = urllib.request.Request(url) #指定请求头(使用浏览器代理打开) req.add_header("user-agent","Mozilla/5.0") #打开网站 response = urllib.request.urlopen(req) #打印状态码 print(response.getcode()) #打印下载的内容 print(response.read())
二.Urllib库的基本使用:
1.扒取网页:
扒取网页和基本代码 首先我们调用的是 urllib2 库里面的 urlopen 方法,传入一个 URL,这个网址是百度首页,协议是 HTTP 协议,当然你也可以把 HTTP 换做
FTP,FILE,HTTPS 等等,只是代表了 一种访问控制协议,urlopen 一般接受三个参数,它的参数如下:urlopen(url, data, timeout)。
import urllib.request url="http://www.baidu.com" responsel=urllib.request.urlopen(url) #response 响应 print(responsel.getcode()) # 打印状态码 print(responsel.read()) # 页面以代码方式打印
2.post方式数据传递:
我们引入了 urllib 库,现在我们模拟登陆 CSDN,当然上述代码可能登陆不进去,因为 CSDN 还有个流水号的字段,没有设置全,比较复杂在这里就不写上去了,在此只是说明登录的原理。一般的登录网站一般是这种写法。 我们需要定义一个字典,名字为 values,参数我设置了 username 和 password,下面利用 urllib 的 urlencode 方法将字典编码,命名为 data,构建 request 时传入两个参数,url 和 data,运行程序,返回的便是 POST 后呈现的页面内容。 注意上面字典的定义方式还有一种,下面的写法是等价的
import urllib from urllib import request, parse # # res = request.urlopen("http://www.baidu.com") # print(res.read()) # # #构造一个请求 # req = request.Request("http://www.baidu.com") # #再打开网页 # resp = request.urlopen(req) # #读取网页内容 # print(resp.read()) #定义一个参数 写入用户名和密码 values = {"username":"xxxxxx","password":"xxxxxxx"} #定义参数编码 values2 = urllib.parse.urlencode(values).encode(encoding='UTF8') #写url url = "http://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn" #构造request请求 将参数带入 request = request.Request(url,values2) #打开获取到的请求页面 res = urllib.request.urlopen(request) #答应网页内容 print(res.read())
3.GET方式数据传递:
GET 方式我们可以直接把参数写到网址上面,直接构建一个带参数的 URL 出来即可。
import urllib import urllib2 values={} values['username'] = "1016903103@qq.com" values['password']="XXXX" data = urllib.urlencode(values) url = "http://passport.csdn.net/account/login" geturl = url + "?"+data request = urllib2.Request(geturl) response = urllib2.urlopen(request) print response.read()
ps:你可以 print geturl,打印输出一下 url,发现其实就是原来的 url 加?然后加编码后的参数 http://passport.csdn.net/account/login?username=1016903103%40qq.com&password=XXXX
三.爬虫程序添加cookie:
1.cookie:
Cookie,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的。
2.获取Cookie保存到文件:
#设置文件路径, 用来保存Cookie filename = 'cookie.txt' # 声明一个MozillaCookieJar 来保存cookie到文件‘ cookie = cookiejar.MozillaCookieJar(filename) #利用request 的HTTPCookieProcessor创建cookir处理器 handl = request.HTTPCookieProcessor(cookie) #通过handl 来构建 openr openr = request.build_opener(handl) #创建请求 resp = openr.open("http://www.baidu.com") #cookie保存到文件,ignore_discard就算cookie失效也要保存,ignore_expires 覆盖文件保存 cookie.save(ignore_discard=True, ignore_expires=True)
3.从文件中获取Cookie并访问:
from http import cookiejar from urllib import request # 创建cookie cookie = cookiejar.MozillaCookieJar() # 从文件读取cookie内容到变量 cookie.load('cookie.txt',ignore_expires=True,ignore_discard=True) # 创建cookie处理器 handler = request.HTTPCookieProcessor(cookie) # 构造下载器 opener = request.build_opener(handler) # 创建请求的request req = request.Request("http://www.baidu.com") # 下载页面 resp = opener.open(req) print(resp.read())
4.利用 cookie 模拟网站登录:
from urllib import request import urllib from http import cookiejar #定义文件名 filename = 'cookie.txt' # 创建cookie cookie = cookiejar.MozillaCookieJar(filename) # 创建cookie 处理器 handler = request.HTTPCookieProcessor(cookie) # 构造下载器 opener = request.build_opener(handler) # 定义data 写入 帐号 密码 data = urllib.parse.urlencode({ "username":"xxxxxx", "password":"xxxxx" }).encode(encoding="UTF8") # 写url loginurl = "https://www.mosoteach.cn/web/index.php?c=passport&m=index" #模拟登录 result = opener.open(loginurl,data) #保存cookie到文件 cookie.save(ignore_discard=True,ignore_expires=True) #利用保存的cookie请求新网站 new_url = "https://www.mosoteach.cn/web/index.php?c=user&m=account_information" # 请求新网页 try: result = opener.open(new_url) except request.HTTPError as e: if hasattr(e,"code"): print(e.code) except request.URLError as e: if hasattr(e,"reason"): print(e.reason) else: print(result.read())
以上程序的原理如下 创建一个带有 cookie 的 opener,在访问登录的 URL 时,将登录后的 cookie 保存下来,然后利用这个 cookie 来访问其他网址。
四.正则表达式:
1.正则表达式:
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,
组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
2.正则表达式的语法规则:
import re # 定义正则规则,r表示原生字符串 pattern = re.compile(r"hello") # 匹配字符,math函数会从第一个字符开始匹配 result1 = re.match(pattern,"hello he") # .span() 获取字符串位置 if result1: print(result1 ) # .group() 获取字符 result2 = re.match(pattern,"hell hello") if result2: print(result2) else: print("no")
import re # 定义正则规则 match 只能从头匹配,如果出现了不一样就断了直接为错 pattern = re.compile(r'a.c') # .表示容易字符 例:abc , asc, acc....都符合正则 res1 = re.match(pattern, "a2c") print(res1) # 匹配斜杆 点 # 这里不能用 r 否者\.会变成字符串去匹配 而不是作为 . 去进行匹配 pattern2 = re.compile('a\.c') res2 = re.match(pattern2, "a.ca.casdkfj") print(res2) # 匹配斜杆 pattern3 = re.compile("a\\\c") # \\将 \ 转义 res3 = re.match(pattern3, "a\cvvdv") print(res3) # 。group 会显示 a\c # 匹配部分字符 pattern4 = re.compile(r"a[a-f,A-F]c") res4 = re.match(pattern4, "aAcddd") print(res4) # 匹配数字 pattern5 = re.compile("a\dc") # \d 表示数字 \转义 \D 大写D表示非数字 res5 = re.match(pattern5, "a6cc") print(res5) #匹配空白 pattern6 = re.compile(r'a\sc') # \s 小写s 表示空格 大S 表示非空格 res6 = re.match(pattern6,"a c") print(res6) # 匹配个数 * 表示 可以有 0到无数个 该字符 pattern7 = re.compile(r'abc*') res7 = re.match(pattern7,"ab") res8 = re.match(pattern7,"abcccccc") print(res7) print(res8)
import re #边界字符 pattern = re.compile(r'^efg') #^ 再在多行中每行都匹配 已ccc开头的 res = re.search(pattern,'efgxxxxxx') print(res) pattern = re.compile(r'ccc$') # $ 再在多行中每行都匹配 已ccc结尾的 res = re.search(pattern,'ssssssccc') print(res) pattern = re.compile(r'\Aaaa') # \A在前 表示 仅匹配字符串aaa开头 res = re.search(pattern,'aaaefgx1xxaaaxxx') print(res) pattern2 = re.compile(r'efg\Z') # \Z在后 表示 仅匹配字符串结尾的efg res = re.search(pattern2,'efg---efg') print(res) pattern2 = re.compile(r'a\b!bc') # \b 匹配\w 和\W之间 res = re.search(pattern2,'a!bc') print(res) pattern2 = re.compile(r'abc|efg') # str1 | str2 先匹配str1 成功则结束 否则匹配str2 res = re.search(pattern2,'abeeeeefgxx') print(res) pattern2 = re.compile(r'(abc){2}a(123|456)c') # () 分组 必须匹配到分组中的字符 (abc){2} 2份abc (123|456) 仅匹配括号中的字符串 res = re.search(pattern2,'xxxxxabcabca456cxxxx') print(res) pattern2 = re.compile(r'(?P<id>abc){2}') # (?p<别名>str) 为分组的str取一个别名 便于后面调用 res = re.search(pattern2,'abcabc') print(res) pattern2 = re.compile(r'(?P<name>abc)---(?P=name)') # 先为第一个分组取别名name 在---后的第二个分组中调用 res = re.search(pattern2,'abc---abc') print(res) pattern2 = re.compile(r'(\b)---\1') # \数字 表示将前面的分组 在后面使用 类型 个数都要一致 res = re.search(pattern2,'2---2') print(res) pattern2 = re.compile(r'(\w+)---\1+') # \数字 表示将前面的分组 在后面使用 类型 个数 字符 都要一致 res = re.search(pattern2,'sss---sss') print(res)

浙公网安备 33010602011771号