爬虫基础

一.爬虫入门

   1.爬虫是什么?

   爬虫:一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。

   2.爬虫原理

  1. 获取初始的URL。初始的URL地址可以由用户人为地指定,也可以由用户指定的某个或某几个初始爬取网页决定。

  2. 根据初始的URL爬取页面并获得新的URL。获得初始的URL地址之后,首先需要爬取对应URL地址中的网页,爬取了对应的URL地址中的网页后,将网页存储到原始数据库中,并且在爬取网页的同时,发现新的URL地址,同时将已爬取的URL地址存放到一个URL列表中,用于去重及判断爬取的进程。

  3. 将新的URL放到URL队列中。在第2步中,获取了下一个新的URL地址之后,会将新的URL地址放到URL队列中。

  4. 从URL队列中读取新的URL,并依据新的URL爬取网页,同时从新网页中获取新URL,并重复上述的爬取过程。

  5. 满足爬虫系统设置的停止条件时,停止爬取。在编写爬虫的时候,一般会设置相应的停止条件。如果没有设置停止条件,爬虫则会一直爬取下去,一直到无法获取新的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)

 

posted @ 2022-03-11 22:21  and脱发周大侠  阅读(56)  评论(0)    收藏  举报