爬虫与信息提取

一、爬虫规则

1.Requests库入门

1.1 安装
1.2 Requests库get()方法
1.3 爬取网页的通用代码框架
1.4 HTTP协议及Requests库方法
1.5 Requests库主要方法解析

2.爬虫规则

2.1 爬虫引发的问题
2.2 Robot协议
2.3 Robot协议的遵守方式

3.Requests库实战

3.1 京东商品页面爬取
3.2 亚马逊商品页面爬取
3.3 百度、360搜索结果爬取
3.4 IP归属地查询

二、爬虫之提取

1.BeautifulSoup入门

BeautifulSoup库是解析、遍历、维护"标签树“的功能库。

import requests
from bs4 import BeautifulSoup
r = requests.get("https://www.230book.com/book/8304/")
r.encoding = "gbk"
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
#demo必须是文本,不可以是链接
1.1 安装

pip install beautifulsoup4

1.2 引用

from bs4 import BeautifulSoup
bs4为beautifulsoup库的名称,B和S要大写。

1.3 BS4的使用
soup = BeautifulSoup('<p>date</p>',"html.parser") 
#'<p>date</p>'是要加工的页面代码,支持字符串、变量,不支持http链接
#"html.parser"是页面代码解释器

?页面解释器还包括:

标签名称形式属性
p<p class = "title"> ...</p>class 代表

HTML解释器

解释器使用方法条件
bs4的HTML解释器BeautifulSoup(mk,‘html.parser’)安装bs4
lxml的HTML解释器BeautifulSoup(mk,‘lxml’)pip install lxml
lxml的XML解释器BeautifulSoup(mk,‘xml’)pip install lxml
html5lib的解释器BeautifulSoup(mk,‘html5lib’)pip install html5lib

如果需要提升性能,或更准确的xml格式,可以使用上述对应解释器。

1.4 BS4的基本方法
基本元素说明格式
Tag标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾html.tag
Name标签的名字,<p>....</p>的名字是’p‘<tag>.name
Attributes标签的属性,字典格式<tag>.attrs
NavigableString标签内非属性字符串,<>....</>中字符串<tag>.string
Commnet标签内字符串的注释部分,特殊的Comment类型

以获取一个小说目录为例(https://www.230book.com/book/8304/)

import requests
from bs4 import BeautifulSoup

r = requests.get("https://www.230book.com/book/8304/")
r.encoding = "gbk"
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
print(soup.prettify())
#prettify为标签内容

错误的使用:
soup = beautifulsoup(r.text)
soup = beautifulsoup("https://python123.io/ws/demo.html",'html.parser)
这是错误的使用,beautifulsoup的参数必须是用html解释器的处理过的文档,应该是
soup = beautifulsoup(r.text,'html.parser)

  • 试着写出prettify与text的区别?
Tag (标签)
soup.a
Out[41]: <a href="https://www.230book.com">顶点小说</a>
#获取第一个标签a
soup.li
Out[42]: <li><a href="/">首页</a></li>
#获取第一个标签li
Name (标签名字)
soup.li.name
Out[43]: 'li'
soup.a.name
Out[44]: 'a'
Attributes(标签的属性)

Attributes是字典(dic)类型

例如:调取标签a的属性class字段

r = requests.get("https://python123.io/ws/demo.html")
soup = BeautifulSoup(r.text,"html.parser")
soup.a.attrs
Out[62]: 
{'href': 'http://www.icourse163.org/course/BIT-268001',
 'class': ['py1'],
 'id': 'link1'}
soup.a.attrs['class']
Out[63]: ['py1']
#调取标签a的属性class字段
NavigableString (标签中的字符串)

可以跨越多个标签层次

find_all()

基于BS4对象的方法,对HTML对象进行标签检索。
在这里插入图片描述
<tag>.find_all(...)方法等同于<tag>(...)括号中引号的部分,两者等同。

  • 如何从find_all的列表中获取某个属性,组成一个新的列表

  • 扩展方法
    在这里插入图片描述

实例:
soup('ul')代表经解释器解析后的html格式,
ul.attrs代表soup中标签为’ul’的属性的列表,此列表元素为辞典格式。例如:{‘class’: [’_chapter’]}
.a 代表标签为a的第一个,(‘a’) 代表所有标签为a的列表。

1.5 基于BS4库的标签遍历方法

在这里插入图片描述

下行遍历
属性说明
.contents子节点的列表,将<tag>所有子节点存入列表
.children子节点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants子孙节点的迭代类型,包含所有子孙节点,用于循环遍历
上行遍历
属性说明
.parent节点的父标签
.parents节点的所有先辈标签的迭代类型,用于循环遍历先辈节点
import requests
from bs4 import BeautifulSoup

r = requests.get("https://www.230book.com/book/8304/")
r.encoding = "gbk"
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
for parent in soup.li.parents: #遍历标签`<li>`的先辈标签
    if parent is None:
        print(parent) #如果parent为空,则返回结果[document]
        #遍历到soup本身时,它不存在.name的属性
    else:
        print(parent.name)
平行遍历
属性说明
.next_sibling返回按照HTML文本顺序的下一个平行节点标签
.previous_sibiling返回按照HTML文本顺序的上一个平行节点标签
.next_sibilings迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_sibilings迭代类型,返回按照HTML文本顺序的前续所有平行节点标签

任何一个节点他的平行节点有可能是NavigableString类型的字符串

1.6 基于BS4库的HTML格式化和编码

如何让HTML页面更加友好的显示,

HTML.prettify()

为HTML文本在每个标签后增加换行符,也可以处理单一标签

BS4默认utf-8编码

2.信息组织与提取

2.1 信息标记的三种形式
XML

与HTML类似的信息标记形式
在这里插入图片描述

JSON

有类型的键值对,键和值增加""来表达是字符串的形式,如果是数字则不加。以此来表示他是有数据类型的键值对。如:
"name" : "北京理工大学"
当值中有多个信息时,用[,]来组织,如:
"name" : ["北京理工大学","延安自然科学院"]
键值对之间可以嵌套使用,在值使用键值对时,用{}来组织。如:
"name" : { "newname" : "北京理工大学","oldname" : "延安自然科学院"}
在这里插入图片描述

YAML

是一种递归的定义。
在这里插入图片描述

2.2 三种信息标记形式的比较
2.3 信息提取的一般方法

方法一:完整解析信息的标记形式,再提取相关信息;
方法二:直接搜索关键信息;
实例
提取HTML中所有URL链接
思路:
1)搜索所有<a>标签
2)解析<a>标签格式,提取href后的链接内容

import requests
from bs4 import BeautifulSoup

r = requests.get("https://www.230book.com/book/8304/")
r.encoding = "gbk"
demo = r.text
soup = BeautifulSoup(demo,"html.parser")

for link in soup.find_all('a'):
    #if link.parent.name = 'li':
    #link.parent.name不是指定的标签列表中的某一项,所以上条语句不成立
    print(link,'---',link['href'])
  • link.get(‘herf’)的使用方法同link[‘href’]。原理?
2.4 基于BS4库的HTML内容查找

3.实例-爬取中国大学排名

网站来源:2020软科中国大学排名
http://www.zuihaodaxue.com/zuihaodaxuepaiming2020.html

  • 步骤一 获取HTML文本
  • 步骤二 解析文本,定位标签树,导入到列表
  • 步骤三 输出列表,调整格式
import requests
from bs4 import BeautifulSoup
import bs4

def getHtmlText(url,hd):   
    try:
        r = requests.get(url,timeout = 30,headers = hd)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""

def fillUnivList(ulist,html): #核心函数

    soup = BeautifulSoup(html,"html.parser")
    #搜索内容的标签树结构是<tbody>,<tr>,<td>,需要的内容在<td>中,所以如下:
    for tr in soup.find('tbody').children:
        #为了准确搜索需要的内容,所以需要从目标内容的父标签(或先辈标签)着手,才能更准确
        #找到代表唯一标签索引树
        if isinstance(tr, bs4.element.Tag): #判断tr标签中不属于标签对象的元素
            tds = tr('td') #标签td也是一个列表
            ulist.append([tds[0].string,tds[1].string,tds[2].string])
            #tds是标签以及列表属性,引用元素是需要注意方法
#虽然没有return,但ulist是一个列表类型,该函数相当于加工ulist列表,增加元素进入列表;
#相当于该函数返回的就是参数ulist列表

def printUnivList(ulist,num):
    tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}\t"
    print(tplt.format("排名","学校","所在城市",chr(12288)))
    #
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0],u[1],u[2],chr(12288)))

          
def main(): #主函数
#将需要设置的参数集中在此
#执行相关函数或方法
    uinfo = []
    url = 'http://www.zuihaodaxue.com/zuihaodaxuepaiming2020.html'
    hd = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko)'}
    Html = getHtmlText(url,hd)
    fillUnivList(uinfo, Html)
    printUnivList(uinfo, 20)
    
main() #执行主函数
    

三、实战

1. 淘宝商品爬取

#CrowTaobaoPrice.py
import requests
import re
 
def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""
     
def parsePage(ilt, html):
    try:
        plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
        tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
        for i in range(len(plt)):
            price = eval(plt[i].split(':')[1])
            title = eval(tlt[i].split(':')[1])
            ilt.append([price , title])
    except:
        print("")
 
def printGoodsList(ilt):
    tplt = "{:4}\t{:8}\t{:16}"
    print(tplt.format("序号", "价格", "商品名称"))
    count = 0
    for g in ilt:
        count = count + 1
        print(tplt.format(count, g[0], g[1]))
         
def main():
    goods = '书包'
    depth = 3
    start_url = 'https://s.taobao.com/search?q=' + goods
    infoList = []
    for i in range(depth):
        try:
            url = start_url + '&s=' + str(44*i)
            html = getHTMLText(url)
            parsePage(infoList, html)
        except:
            continue
    printGoodsList(infoList)
     
main()

2. 股票定向爬虫

#CrawBaiduStocksA.py
import requests
from bs4 import BeautifulSoup
import traceback
import re
 
def getHTMLText(url):
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""
 
def getStockList(lst, stockURL):
    html = getHTMLText(stockURL)
    soup = BeautifulSoup(html, 'html.parser') 
    a = soup.find_all('a')
    for i in a:
        try:
            href = i.attrs['href']
            lst.append(re.findall(r"[s][hz]\d{6}", href)[0])
        except:
            continue
 
def getStockInfo(lst, stockURL, fpath):
    for stock in lst:
        url = stockURL + stock + ".html"
        html = getHTMLText(url)
        try:
            if html=="":
                continue
            infoDict = {}
            soup = BeautifulSoup(html, 'html.parser')
            stockInfo = soup.find('div',attrs={'class':'stock-bets'})
 
            name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
            infoDict.update({'股票名称': name.text.split()[0]})
             
            keyList = stockInfo.find_all('dt')
            valueList = stockInfo.find_all('dd')
            for i in range(len(keyList)):
                key = keyList[i].text
                val = valueList[i].text
                infoDict[key] = val
             
            with open(fpath, 'a', encoding='utf-8') as f:
                f.write( str(infoDict) + '\n' )
        except:
            traceback.print_exc()
            continue
 
def main():
    stock_list_url = 'https://quote.eastmoney.com/stocklist.html'
    stock_info_url = 'https://gupiao.baidu.com/stock/'
    output_file = 'D:/BaiduStockInfo.txt'
    slist=[]
    getStockList(slist, stock_list_url)
    getStockInfo(slist, stock_info_url, output_file)
 
main()

四、爬虫框架

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值