爬虫

发布于 2020-05-13  1145 次阅读


4. 第二阶段的实战

1.世界大学排名的定向爬虫

import requests
import bs4

def getHTMLText(url):
    try:
        kv = {'User-Agent': 'Mozilla/5.0'}
        r = requests.get(url, headers = kv, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return(r.text)
    except:
        return("")
        
def fillUnivList(uList, html):
    soup = BeautifulSoup(html, 'html.parser')
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):
            tds = tr('td')
            uList.append([tds[0].string, tds[1].string, tds[4].string])

def printUnivList(uList, num):
    template = "{0:^10}\t{1:{3}^10}\t\t{2:^10}"
    print(template.format("排名","学校","总分",chr(12288)))
    for i in range(num):
        u = uList[i]
        print(template.format(u[0], u[1], u[2], chr(12288)))

if __name__ == "__main__":
    uinfo = []
    url = "http://www.zuihaodaxue.com/ARWU2019.html"
    html = getHTMLText(url)
    fillUnivList(uinfo, html)
    printUnivList(uinfo, 20)

运行后输出:

 runfile('D:/Anaconda Spyder/crawler.py', wdir='D:/Anaconda Spyder')
    排名              学校                      总分    
    1              哈佛大学                   100.0   
    2             斯坦福大学                    75.1   
    3              剑桥大学                    72.3   
    4             麻省理工学院                   69.0   
    5            加州大学-伯克利                  67.9   
    6             普林斯顿大学                   60.0   
    7              牛津大学                    59.7   
    8             哥伦比亚大学                   59.1   
    9             加州理工学院                   58.6   
    10            芝加哥大学                    55.1   
    11           加州大学-洛杉矶                  50.8   
    11             耶鲁大学                    50.8   
    13            康奈尔大学                    49.8   
    14          华盛顿大学-西雅图                  48.7   
    15            伦敦大学学院                   47.9   
    16           约翰霍普金斯大学                  47.6   
    17           宾夕法尼亚大学                   47.3   
    18          加州大学-圣地亚哥                  47.1   
    19          苏黎世联邦理工学院                  46.1   
    20           加州大学-旧金山                  42.2   

5. re库

正则表达式是用来简洁表达一组字符串的,比如以下字符:

"PN", "PYN", "PYTN", "PYTHN", "PYTHON"

可以用正则表达式:P(Y|YT|YTH|YTHO)?N 表示

1.正则表达式的语法

正则表达式是由字符和操作符组成的

常用操作符:

  • . ——表示任何单个字符
  • [] ——字符集,对单个字符给出取值范围
  • [^] ——非字符集,对单个字符给出排除范围
  • * ——前一个字符0次或者无限次扩展
  • + ——前一个字符1次或者无限次扩展
  • ? ——前一个字符0次或者1次次扩展
  • | ——左右表达式任意一个
  • {m} ——扩展前一个字符m次
  • {m, n} ——扩展前一个字符m至n次(包括n)
  • ^ ——匹配字符串开头
  • $ ——匹配字符串结尾
  • () ——分组标记,内部只能使用 | 操作符
  • \d ——数字,等价于[0-9]
  • \w ——单词字符,等价于[A-Za-z0-9_]

raw string——原生字符串类型, '\' 转义符不起作用。若包含转义符,正则表达式最好使用 raw string 类型

2. re库主要的功能函数

  • re.search():搜索匹配正则表示式的第一个位置,返回match对象
  • re.match():从开始位置起匹配正则表示式,返回match对象
  • re.findall():以列表形式返回所有能匹配的字符串
  • re.split():将正则表达式的结果进行分割,以列表形式返回
  • re.finditer():返回匹配结果的迭代类型,每个迭代元素都是match对象
  • re.sub():替换所有匹配正则表达式的字串,返回替换后的字符串

3. 正则表达式对象

re.compile(pattern, flag=0)——将正则表达式的字符串形式编译为正则表达式对象

regex = re.compile(pattern, flag=0)

4. match对象的属性

  • .string:待匹配的文本
  • .re:匹配时使用的pattern对象,正则表达式
  • .pos:正则表达式搜索文本的开始位置
  • .endpos:正则表达式搜索文本的结束位置

5. match对象常用的方法

  • .group(0):获得匹配后的字符串
  • .start():匹配字符串在原始字符串的开始位置
  • .end():匹配字符串在原始字符串的结束位置
  • .span():返回(.start(), .end())

6. re库的贪婪匹配和最短匹配

re库默认采用贪婪匹配,即输出匹配最长的字串

import re
match = re.search(r'PY.*N', 'PYANSICJHN')
print(match.group(0)) #out: PYANSICJHN

若想输出最短字串,要加一个 '?'

import re
match = re.search(r'PY.*?N', 'PYANSICJHN')
print(match.group(0)) #out: PYAN

6. 第三阶段实战

1. 淘宝信息定向爬取

需要填写header,否则会跳到登陆验证页面。头部的获取方法点这里 或者看下一段括号内的方法,获得后把内容填到第6行的 kv 中。

这里要感谢B站大佬 浪精灵 给出的方法
(首先登陆你的淘宝账号,然后按 F12 进入检查,在上面的 network 的第一行中拖到最后,有一个Request Headers,右键 Copy-->Copy as URL(bash),然后打开这个网站(点这里)。 在里面把复制的内容放进去,选择 Python 然后会发现右边有一个 headers:{省略...},把这个 headers 放进代码,用一个变量储存,然后在代码中的r equest.get(url,headers=你刚才复制的内容,也就是那个变量),这个时候你再请求 request.text 返回的就是你要的页面)

import re
import requests

def getHTMLText(url):
    try:
        kv = {} #获取方法请见上面
        r = requests.get(url, headers = kv, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        #print(r.text)
        return(r.text)
    except:
        return("")
        
def parsePage(ilt, hyml):
    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):
    template= "{:4}\t{:8}\t{:16}"
    print(template.format("序号","价格", "名称"))
    count = 0
    for g in ilt:
        count += 1
        print(template.format(count, g[0], g[1]))
    
    
if __name__ == "__main__":
    goods = 'switch'
    depth = 2
    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)

输出结果(这截取了前20行):

In [32]: runfile('D:/Anaconda Spyder/crawler.py', wdir='D:/Anaconda Spyder')
序号      价格              名称              
   1    2099.00         Nintendo Switch 任天堂家用游戏机续航版增强版 掌机NS体感游戏机 国行Switch游戏机
   2    320.00          Switch NS游戏 异度之刃 异度神剑决定终极决战版 十一区中文订购
   3    1410.00         任天堂switch续航版ns日版 港版 国行ns主机lite掌机动物之森限定
   4    2099.00         Nintendo Switch 任天堂家用游戏机续航版增强版 掌机NS体感游戏机 国行Switch游戏机
   5    3499.00         任天堂NS Switch续航主机 动物之森限定版 动森限定 现货电玩巴士
   6    1449.00         电玩巴士 任天堂Switch续航加强 NS国行日版Lite游戏主机 掌机
   7    1449.00         创想任天堂Switch主机Lite游戏机NS续航版国行日版动物之森限定
   8    2049.00         现货任天堂 NS switch动物之森 森友会 限定版主机 游戏机 港日版
   9    2049.00         创想电玩任天堂 Switch新版游戏主机NS续航国行港日版限定 健身环
  10    1409.00         任天堂Switch主机Lite游戏机续航版NS国行港日版动物之森限定版
  11    1419.00         任天堂switch Lite掌机NS游戏机 动物森友会限定机 续航版 日版
  12    999.00          抖音XBOX360ES体感游戏机switch电玩PS双人电视体感wiiu家用4人on
  13    1419.00         国行 任天堂switch lite游戏机NS主机续航加强版动物之森限定日版
  14    1439.00         任天堂Switch NS主机 Lite游戏掌机 续航加强版 动物之森日版国行
  15    978.00          现货 NS游戏 健身环大冒险NS Ring fit Adventure 中文 switch
  16    1408.00         任天堂switch NS主机 Lite掌机 续航加强版主机 宝可梦 剑盾 粉色
  17    886.00          任天堂Switch游戏 NS健身环大冒险 Ring fit Adventure 现货即发
  18    1419.00         任天堂switch主机lite游戏机NS续航加强版动物之森限定港日版国行
  19    1409.00         任天堂switch lite游戏机NS主机续航加强版动物之森限定机港日版
  20    2049.00         北京华冕 任天堂Switch NS主机掌机游戏机  新续航 国行/日港版