慕课BIT嵩老师爬虫课笔记

一直想学python,在中国大学慕课上发现了嵩老师的python系列专题课程,就首先试着听了听嵩老师的爬虫课,虽然时间有点短并且内容也不够深入,但是讲得很生动,于是就记了一些笔记,也稍微加入了一些自己的见解和总结

Requests库


主要方法

  • r = requests.get(url)
  • r = requests.get(url, params=None, **kwargs),params指url中额外的访问参数,kwargs指12个控制访问参数
  • r = requests.post(url, data=None, **kwargs)
  • r = requests.request(‘get’, url, params, **kwargs)
  • r = requests.head(url) 只获得请求头

一些常用的访问控制参数:
params 请求参数
data 请求体参数
json json格式数据作为请求体内容
headers 定制请求头
cookies 字典或者CookieJar
auth 元组,支持http认证功能
files 字典类型,传输文件
proxies 字典,设置访问代理服务器
allow_redirects 重定向开关,默认开
verify 认证ssl开关,默认开
cert 本地ssl路径
##Response对象的常用属性

  • r.status_code 返回状态码
  • r.text 响应内容的字符串形式,即url对应的页面,如果不是get的请求方式的话则打印的是请求体
  • r.encoding header中的响应编码方式
  • r.apparent_encoding 从内容中分析出的响应编码方式
  • r.content 响应内容的二进制形式
  • r.url 请求时的url

1.常用r.encoding = r.apparent_encoding
来防止页面乱码。
2.使用r.raise_for_status()在返回状态不是200时产生异常

其他使用技巧

伪装成浏览器:

r=requests.get(url,headers={'user-agent':'Mozilla/5.0'})

Robots协议


查看方法

url/robots.txt

BeautifulSoup库


获得soup

soup=BeautifulSoup('<html>...</html>','html.parser')

常用解析器:

  • html.parser bs库自带的解析器,解析html;
  • lxm 需要安装lxml库,解析html,xml;
  • xml 需要安装lxml库,解析xml,笔者使用时感觉对xml文档的容错能力较低,不如lxml;
  • html5lib 需要安装html5lib

##BeautifulSoup基本元素

  • Tag 标签
  • Name 标签名,可通过tag.name获得
  • Attributes 标签属性,字典形式组织,通过tag.attrs获得
  • NavigableString 非属性字符串,可通过tag.string获得

注:如果标签内有多个分离的字符串,则返回None,用tag.text则可以返回由这些分离的字符串连接起来的str类型

  • Comment 标签内注释

标签树的遍历

下行遍历

  • .contents 返回直接子节点的列表
  • .children 返回直接子节点的迭代类型
  • .descendants 返回所有后裔节点的迭代类型

上行遍历

  • .parent 节点的父标签
  • .parents 节点的所有先辈标签的迭代类型

平行遍历

  • .next_sibling 下一个平行节点标签
  • .next_siblings 返回所有后续平行节点的迭代类型
  • .previous_sibling 上一个平行节点标签
  • .previous_siblings 返回前续所有平行节点的迭代类型

注:平行遍历发生在同一父节点下

友好显示

print(soup.prettify())

常用的信息表示形式与信息提取方法

  • 形式:xml,json,yaml
  • 提取方法:形式解析与搜索方法

BeautifulSoup标签查找方法

  • *tag.find_all(name,attrs,recursive,string,*kwargs) 返回所有符合要求的标签列表,name为要检索的标签名;attrs限定属性;recursive表示是否递归检索所以子孙,默认true;string表示对字符串区域检索字符串,如果限定了该属性,此时返回的是字字符串列表。

注:tag(‘a’)等价与tag.findall(‘a’)

  • tag.find() 返回搜索到的第一个结果

注:tag.a等价于tag.find(‘a’)

  • tag.find_parents() 在所有先辈节点中搜索,返回一个列表返回所有查找到的结果
  • tag.find_parent() 在所有先辈节点中返回第一个匹配结果
  • tag.find_next_siblings() 在后续平行节点中返回一个列表包含所有所有匹配结果
  • tag.find_next_sibling() 返回后续节点中第一个匹配的结果
  • find_previous_siblings()
  • find_previous_sibling()

注:所有这些函数的参数都同find_all()

案例:中国大学排名定向爬虫

format函数

"{:^10}\t{:^6}\t{:^10}".format("排名","学校名称""总分")

解决中文对齐问题:

"{0:^10}\t{1:{3}^6}\t{2:^10}".format("排名","学校名称","总分",chr(12288))

chr(12288) 表示中文空格:{3}表示用format函数中索引为3的参数进行填充

Re库


常用符号

  • . 匹配任意单个字符
  • [] 字符集,对单个字符给出取值范围
  • [^] “非”字符集,对单个字符给出排除范围
  • * 前一个字符0次或多次扩展
  • + 1次或多次扩展
  • ? 0次或1次扩展
  • | 左右表达式任意一个
  • {m} 前一个字符扩展m次
  • {m,n} 扩展m至n次(含n)
  • ^ 匹配字符串开头
  • $ 匹配字符串结尾
  • ()
  • \d 数字,等价与[0-9]
  • \w 单词字符,等价与[A-Za-z0-9_]

经典正则表达式

  • ^[A-Za-z]+$ 由26个字母组成的字符串
  • [\u4e00-\u9fa5] 匹配中文字符
  • (([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]) 匹配ip地址

Python的raw string类型

r'text' 则python不会对字符串中的转义符进行转义,正则表达式一般使用raw string

Re库主要函数

  • re.search(pattern,string,flags=0) 搜索匹配正则表达式的第一个位置,返回match对象
  • re.match() 从字符串开始位置匹配正则表达式,返回match对象,可以使用在if语句中
  • re.findall() 以列表类型返回全部能匹配的子串
  • re.split(pattern,string,maxsplit=0,flags=0) 按照正则表达式匹配结果对字符串进行分割,返回列表类型;maxsplit表示最大分割数,剩余部分作为最后一个元素输出
  • re.finditer() 返回匹配结果的迭代类型,每一个迭代元素是match对象
  • re.sub(pattern,repl,string,count=0,flags=0) 替换所有匹配正则表达式的子串,返回替换后的字符串;repl表示替换匹配字符串的字符串,count表示最大替换次数

flags包括如下:

  • re.IGNORECASE re.I 忽略大小写匹配
  • re.MULTILINE re.M 正则表达式的^操作符能将每行当做匹配开始
  • re.DOTALL re.S 正则表达式的.操作符可以匹配包括换行符在内的一切字符,如果不指定这个模式,则.不能匹配换行符

##Re库的另一种等价用法

pat=re.compile(r'[1-9]\d{5}')
rst=pat.search('BIT 100081')

Match对象介绍

Match表示一次匹配的结果,包含很多匹配信息

Match对象的属性

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

Match对象的方法

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

贪婪匹配与最小匹配

Re库默认采用贪婪匹配

最小匹配操作符

  • *?
  • +?
  • ??
  • {m,n}?

案例

网站选取心态:不要纠结与某个网站,多找信息源尝试

判断一个元素是否是标签:

import bs4
isinstance(tr, bs4.element.Tag)

注:前面说的那几个BeautifuSoup元素都是在bs4的element的模块下

Scrapy框架入门


##框架结构
Scrapy的框架结构
5个组件,2个Middleware,包括Downloader Middleware和Spider Middleware

Scrapy常用命令行

  • startproject 创建一个新工程
  • genspider 创建一个爬虫
  • settings 获得爬虫配置信息
  • crawl 运行一个爬虫
  • list 列出工程中所有爬虫
  • shell 启动url调试命令行

Scrapy爬虫编写步骤

步骤1

建立一个scrapy爬虫工程,即生成工程目录

scrapy startproject 工程名

步骤二

在工程中产生一个scrapy爬虫。

进入刚刚创建的目录,输入如下命令:

scrapy genspider 爬虫名称 初始url

spiders目录下会生成 爬虫名称.py,该命令仅用于生成 爬虫名称.py,该文件也可以手动生成。

步骤三

  • 配置初始url:
    打开刚刚生成的py文件,修改start_urls变量

  • 编写解析方式:
    修改parse函数

示例如下:
代码示例
另一个等价版本,使用yield生成器:
yield版本代码示例

步骤四

运行爬虫,命令如下:

scrapy crawl 爬虫名称

yield关键字

包含yield语句的函数是一个生成器,生成器每次产生一个值,然后被冻结,被唤醒后再产生一个值,不断往复。

示例:

def gen(n):
    for i in range(n):
        yield i**2

for i in gen(5):
    print(i, " ", end="")

输出:

0 1 4 9 16

Scrapy爬虫框架的使用步骤

  1. 创建一个工程和Spider模板
  2. 编写Spider
  3. 编写Item Pipeline
  4. 优化配置策略

Scrapy中的几种数据类型

Request类

含义:表示一个http请求,由Spider生成,Downloader执行

属性和方法:

  • url 请求的url地址
  • method 请求对应的http方法,‘get’,'post’等
  • headers 字典类型风格的请求头
  • body 请求主体内容,字符串类型
  • meta 用户添加的拓展信息,在Scrapy内部模块间传递信息使用
  • .copy() 复制该请求

Response类

含义:表示一个http响应,由Downloader生成,Spider处理

属性和方法:

  • url 对应的url地址
  • status 响应状态码
  • headers
  • body
  • flags 一组标记
  • request 产生Response类型所对应的Request对象
  • copy() 复制该响应

Item类

含义:表示一个从html页面中提取的信息内容,由Spider生成,Item Pipline处理,Item类似字典类型,可以按照字典类型操作

Scrapy支持的信息提取方法

  • BeautifulSoup
  • lxml
  • re
  • XPath Selector
  • CSS Selector

CSS Selector示例:
response.css(‘a::attr(href)’).extract()
表示抽取a元素的href属性,返回一个迭代类型

股票数据爬虫案例

非终结parse方法

是一个Request对象的生成器

def parse(self, response):
    for href in response.css('a::attr(href)').extract():
        try:
            stock = re.findall(r"[s][hz]\d{6}", href)[0]
            url = 'https://gupiao.baidu.com/stock/' + stock + '.html'
            yield scrapy.Request(url, callback=self.parse_stock)
        except:
            continue

终结parse方法

也是一个生成器

def parse_stock(self, response):
    infoDict = {}
    stockInfo = response.css('.stock-bets')
    name = stockInfo.css('.bets-name').extract()[0]
    keyList = stockInfo.css('dt').extract()
    valueList = stockInfo.css('dd').extract()
    for i in range(len(keyList)):
        key = re.findall(r'>.*</dt>', keyList[i])[0][1:-5]
        try:
            val = re.findall(r'\d+\.?.*</dd>', valueList[i])[0][0:-5]
        except:
            val = '--'
        infoDict[key]=val
    infoDict.update(
        {'股票名称': re.findall('\s.*\(',name)[0].split()[0] + \
         re.findall('\>.*\<', name)[0][1:-1]})
    yield infoDict

编写Pipelines

步骤:

  1. 配置pipelines.py
  2. 定义对爬取项的处理类
  3. 配置settings.py的ITEM_PIPELINES选项
    示例:

编写pipelines.py:

方法运行顺序为open_spider->process_item->close_spider

class BaidustocksInfoPipeline(object):
    def open_spider(self, spider):
        self.f = open('BaiduStockInfo.txt', 'w')
 
    def close_spider(self, spider):
        self.f.close()
 
    def process_item(self, item, spider):
        try:
            line = str(dict(item)) + '\n'
            self.f.write(line)
        except:
            pass
        return item

配置settings.py:

ITEM_PIPELINES = {
    'BaiduStocks.pipelines.BaidustocksInfoPipeline': 300,
}

300的大小表示执行顺序

优化配置

  • CONCURRENT_REQUESTS Downloader最大并发下载数量,默认32
  • CONCURRENT_ITEMS Item Pipeline最大并发ITEM处理数量,默认100
  • CONCURRENT_REQUESTS_PER_DOMAIN 每个目标域名最大的并发请求数量,默认8
  • CONCURRENT_REQUESTS_PER_IP 每个目标IP最大并发请求数量,默认0,非0有效
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值