python爬取网站之preparation

python爬取网站之preparation

  一:爬取流程

1.准备工作:

  通过浏览器查看目标网页

2.获取数据:

  通过HTTP库向目标网站发送请求,请求可以包含header等信息,如果网站能正常响应,会得到一个REsponse,这就是网页的内容

3.解析内容:

  得到的内容有可能是html,还有可能是xml,可以用页面解析库或者正则表达式进行解析

4.保存数据:

  可以保存为txt文本,也可以保存为数据库,也可以保存为你想要保存的形式

 

二:准备工作:

  1. 允许代码出现中文#-*-coding:utf-8-*-(可以保证在代码中可以出现中文)

  2. 可以加入main函数用于测试程序

    if_name=="_main_":#规范
    ​
    eg:
        if __name__=="__main__":#当程序执行的时候
        #调用main函数
            def main():
                print("hello")
  3. 引入库:import

    #引入系统模块:
    import os
    import sys
    ​
    #引入第三方模块:需要外部引入
    import re       #正则表达式进行文字匹配
    import urllib   #制定url,获取网页数据
    import xlwt     #进行excel操作
    import bs4      #网页解析,获取数据
    from bs4 import BeautifulSoup   #网页解析,获取数据
    import sqlLite3 #进行SQLite数据库操作
    #如何操作,进行外部引入:
    terminal->打开控制台->pip ps4/re/urllib/xlwt#临时安装
    File->setting->project+名字->project interpreter->右上角+号->搜索框搜索引入的包,并添加
  4. 请求数据:post和get请求:

    import urllib.request 
    import urllib.parse     #模拟浏览器,封装数据所用的包  
    #请求网页,获取一个get对象                                                                   
    response=urllib.request.urlopen("http://www.baidu.com")#open一个网页                  
    print(response.read().decode('utf-8'))#输出读取对象的信息,而不是直接输出对象名,注意为了王编码更加流畅,使用utf-8解码 
    #post请求,一般用在模拟用户网站登录的时候,必须给一个封装后的表单,否则直接post是不允许的         
    #这里将数据使用二进制转换,并以utf-8的格式封装到data,并使用parse包封装成浏览器发送请求                  
    data=bytes(urllib.parse.urlencode({"password":"132456"}),encoding="ut
    #使用post请求的时候,必须在最后写明post,并且把封装好的表单写上                                 
    response=urllib.request.urlopen("http://httpbin.org/post",data=data) 
               
    #get请求,同上只需要换成get就好了
  5. 超时现象(也就是网站发现了是爬虫,拒绝访问)

    #使用try块,捕获异常,并在获取request对象的时候,加上timeout属性(检测执行时间)
    try:
        response=urllib.request.urlopen("http://www.baidu.com",timeout=2)
        print(response.read().decode('utf-8'))
    except URLError as E:
        print("URLError")
  6. 获取header响应头

    response.getheaders()#获取所有header的表单
    response.getheader("Server").decode('utf-8')#获取指定的header的值,以utf-8解码
  7. 当遇到418的时候,User-Agent需要改变一下

    #url:请求地址,data:封装程浏览器发送的表单,headers:返回的响应头,method:响应
    url="http://baidu.com"
    headers={
        User-Agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63"
    }
    data=bytes(urllib.parse.urlencode({"password":"132456"}),encoding="utf-8")
    ​
    req=urllib.request.Request(url=url,data=data,headers=headers,method ="POST")
    response=urllib.request.urlopen(req)#注意:这里不是传地址,而是直接传了一个req对象,里面包含了所需要的的素有信息
    print(response.read().decode("utf-8")
    #User-Agent所在位置:F12->NetWork->Header->Request Header->User-Agent后面所有的内容

     

三:获取数据:(可以使用for循环,循环调用实现翻页效果)

def askURL(url):
    #User-Agent必须与其完全一致才行
    head={#模拟浏览器头部信息,向服务器发送消息
        User-Agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.63"
    }
    #这个请求标头request是为了给response服务以及传参的
    request =urllib.request.Request(url,headers=head)
    html=""
    try:
        response=urllib.request.urlopen(request)
        html=response.read().decode("utf-8")#以html的方式读取数据
        print(html)
    except urllib.error.URLError as e:
        if hasatter(e,"code"):#错误1
            print(e.code)
        if hasatter(e,"reason"):#错误2
            print(e.reason)

 

  重点:BeautifulSoup使用方法:

file=open("./baidu.html","rb")
html=file.read()
#这里是核心,将筛选器bs对象创建出来,可以是html对象,也可以是xml对象,自动补全标签
bs=BeautifulSoup(html."html.paser")#第一个参数是将转换的类型,第二个参数是固定格式(文件.paser)
1.获取Tag标签及其内容:
print(bs.title)
print(bs.a)
print(bs.head)
​
2.NavigableString,获取标签里面的内容(字符串)
print(bs.title.tring)
print(bs.a.string)
​
3.BeautifulSoup:获取标签整个文档内容
print(bs)
​
4.attr:获取标签下所存在的元素成员,并且以表单的形式返回
print(bs.a.attrs)
#输出:{‘class':['manbv'],'href':'ahsfiasf'}
5.Comment:是一个特殊的NavigableString,但是输出的时候不包含注释符号
print(bs.a.string)
​
6.contents:遍历文件树
#tag的.content属性可以将tag的子节点以列表的方式输出
print(bs.head.contents)
#用列表索引来获取他的某一个元素
print(bs.head.contents[1])
​
7.遍历文档树:
    soup = BeautifulSoup(html_doc,'lxml')
    #     1、直接使用
    print(soup.html)
    print(type(soup.html)) #类型变成了element_tag
    print(soup.a)
    #     2、获取标签的名称
    print(soup.a.name)
    #     3、获取标签的属性
    print(soup.a.attrs)
    #     4、获取标签的内容
    print(soup.p.text)
    #     5、嵌套选择
    print(soup.html.body.p)
    #     6、子节点、子孙节点
    print(soup.p.children)
    #     7、父节点、祖先节点
    print(soup.b.parent)
    print(soup.b.parents)
    
8.搜索文档树:
格式:
    标签查找与属性查找:
    find与findall
    find找一个
    findall找所有
    标签:
        - 字符串过滤器   字符串全局匹配
            name 属性匹配
            attrs 属性查找匹配
            text 文本匹配
    
        - 正则过滤器
            re模块匹配
    
        - 列表过滤器
            列表内的数据匹配
    
        - bool过滤器
            True匹配
    
        - 方法过滤器
            用于一些要的属性以及不需要的属性查找。
        
    属性:
        - class_
        - id
        
# 第一个参数是解析文本
# 第二个参数是解析器
soup = BeautifulSoup(html_doc, 'lxml')
# 1、字符串
# find的默认参数 第一个是name、第二个是attrs、第四个是text
# name: 根据标签名匹配节点
print(soup.find('p'))  # 获取第一个p标签
print(soup.find_all(name='p'))  # 获取所有的p标签
# attrs: 根据属性查找匹配节点
print(soup.find(attrs={'id': 'p'}))  # 查找id为p的标签
print(soup.find_all(attrs={'class': 'sister'}))  # 查找class为sister的所有标签
# text: 根据文本匹配文档树内的文本
# 推荐配合其他匹配规则使用,否则毫无意义
print(soup.find(text='$37'))  # 查找标签内为$37的文本
# name与text配合使用
print(soup.find_all(name='p', text='$37'))  # 查找所有文本为$37的p标签
# name与attrs配合使用
print(soup.find(name='a', attrs={'id': 'link2'}))  # 查找第一个id为link2的a标签
# attrs与text配合使用
print(soup.find_all(attrs={'id': 'link2'}, text='Lacie'))  # 查找所有id为link2,文本为Lacie的标签
# name、attrs、text组合使用
print(soup.find_all(name='a', attrs={'id': 'link3'}, text='Tillie'))  # 查找所有id为link3,文本为Tillie的a标签
​
​
# 2、正则
print(soup.find(name=re.compile('a')))  # 通过第一个标签名带有a的节点
print(soup.find_all(attrs={'id': re.compile('link')}))  # 匹配所有id名带有link的节点
print(soup.find_all(text=re.compile('and')))  # 匹配所有文本带有"and"的节点
​
​
# 3、列表 (列表内可以匹配多个)
print(soup.find_all(name=['a', re.compile('e')]))  # 匹配所有a标签节点与所有标签中带有e的节点
print(soup.find_all(text=['$']))  # 找不到,因为$是精确查找
print(soup.find_all(text=['$37']))  # 查找$37文本,这样查找是没有意义的
print(soup.find_all(text=[re.compile('$')]))  # 正则中$是特殊字符,所以需要转义
​
​
# 4、bool
print(soup.find_all(name=True))  # 查找所有有标签名的节点
print(soup.find_all(attrs={'id': True}))  # 查找所有有id的节点
print(soup.find_all(text=True))  # 查找所有文本
​
​
# 5、方法
# 写一个只要有class没有id的a标签的函数
def has_class_not_id(arg):
    if arg.name == 'a' and arg.has_attr('class') and not arg.has_attr('id'):
        return arg.name
​
print(soup.find_all(name=has_class_not_id))  # 通过has_class_not_id的函数匹配节点
​
​
# 6、标签与属性查找
# 标签
print(soup.find_all(attrs={'class': 'sister'}))
​
# 属性
# 根据class属性查找,因为class是关键字,所以后面需要加下划线
print(soup.find_all(class_='sister'))
# 根据id属性查找
print(soup.find_all(id='link2'))

 

原文地址:https://www.cnblogs.com/instead-everyone/p/13764908.html