爬虫(详细介绍,由浅入深)

网络爬虫与信息提取笔记

学习python的视频https://www.bilibili.com/video/av69060979?p=1

以爬虫视角,看待网络内容(来源:学习强国平台,北京理工大学学习视频 北京理工大学崇天)

文章目录

    • 网络爬虫与信息提取笔记
    • 1 Requests库入门
      • 1.1 requests库方法
      • 1.2 爬取网页的通用代码框架
      • 1.3Request库网络爬虫实战(5个实例)
        • 1.3.1访问京东商品
        • 1.3.2亚马逊商品页面的爬取
        • 1.3.3百度/360搜索关键词提交
        • 1.3.4网络图片的爬取与存储
        • 1.3.5 IP地址归属地的自动查询
    • 2 网络爬虫的“盗亦有道”
      • 2.1网络爬虫的尺寸
      • 2.2网络爬虫引发的问题
      • 2.3网络爬虫的限制
      • 2.4Robots协议
        • 2.4.1Robots协议基本语法
        • 2.4.2Robots协议的理解
    • 3 解析HTML页面信息标记与提取方法 Beautiful Soup
      • 3.1 beautifu souo(美味汤)对html进行解析,并提取相关信息。
      • 3.2Beautiful Soup (bs4)库的理解
        • 3.2.1Beautiful Soup库解析器
      • 3.3.获取tag标签内容,名字,属性
      • 3.4基于bs4库的遍历方法
        • 3.4.1标签树的下行遍历
        • 3.4.2标签树的上行遍历
        • 3.4.3标签树的平行遍历
      • 3.5基于bs4库的HTML格式输出
        • 输出美化:prettify()方法
    • 4 信息组织与提取
      • 4.1信息标记形式
        • 4.1.1 XML :eXtensible Markup Language
        • 4.1.2 JSON : JavaScript Object Notation
        • 4.1.3 YAML :YAML Ain't Markup Language
      • 4.2信息组织与提取方法
        • 方法一:完整解析信息的标记形式,再提取关键信息
        • 方法二:无视标记形式,直接搜索关键信息
        • 实例:提取HTML中所有的URL标签
      • 4.3基于bs4库的HTML内容的查找方法
        • 4.1. name 参数
        • 4.2attrs参数
        • 4.3recursive参数
        • 4.4string参数
        • 4.5简短模式
    • 5.实例中国大学排名爬虫
        • 中文对齐问题的解决
    • 6 正则表达式库(re)入门
      • 6.1正则表达式常见字符及其含义
      • 6.2正则表达式语法实例
      • 6.3正则表达式编译标志及其含义
      • 6. 正则表达式常用函数
      • 6.4Re库的另一种等价用法
      • 6.5Re库的Match对象(一次匹配的结果)
        • Match对象的属性
        • Match对象的方法,详见6.6
        • 贪婪匹配
        • 最小匹配操作符
      • 6.6 正则表达式常用方法
    • 7 淘宝商品比价定向爬虫实例
        • 程序的结构设计
    • 8股票数据定向爬虫
      • 展示动态显示不换行进度条\r
    • 9 Scrapy爬虫框架
      • Engine:
      • Downloader:
      • Scheduler:
      • Downloader Middleware:
      • Spider:
      • Item Pipelines:
      • Spider Middleware:
      • requests vs scrapy
      • Scrapy常用命令
      • scrapy爬虫的基本使用
        • 步骤一:采用命令行生成一个工程
        • 步骤二:在工程中产生一个Scrapy爬虫
        • 步骤三:配置产生的spider爬虫
        • 步骤四:运行爬虫,获取网页。
      • yield关键字
    • 10 scrapy爬虫的使用步骤
      • Scrapy爬虫的数据类型
        • Request类
        • Response类
        • Item类
      • Scrapy爬虫支持多种HTML信息提取方法
    • 实例:股票数据scrapy爬虫
        • Item类
      • Scrapy爬虫支持多种HTML信息提取方法
    • 实例:股票数据scrapy爬虫

1 Requests库入门

1.1 requests库方法

requests.request() requests.put()
requests.get() requests.patch()
requests.head() requests.delete()
requests.post()

1.2 爬取网页的通用代码框架

try:
    r = requests.get(url, timeout=30)
    r.raise_for_status()#返回200表示访问成功
    r.enconding = r.apparent_encoding
    return r.text
except:
    return "产生异常"
#网络连接有风险,异常处理很重要

1.3Request库网络爬虫实战(5个实例)

1.3.1访问京东商品

import requests
url ="http://item.jd.com/2967929.html"
try:
    r = requests.get(url)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[:100])
except:
    print("爬取失败")

1.3.2亚马逊商品页面的爬取

import requests
url = "https://www.amazon.cn/gp/product/B01M8L5Z3Y"
try:
    kv = {'user-agent':'Mozilla/5.0'}
    r = requests.get(url,headers = kv)
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[1000:2000])
except:
    print("爬取失败")

1.3.3百度/360搜索关键词提交

提供关键词,得到搜索结果

百度的关键词接口:http://www.baidu.com/s?wd=keyword

360的关键词接口:http://www.so.com/s?q=keyword

import requests
keyword = 'python'
try:
    kv = {'wd':keyword}
    r = requests.get("http://www.baidu.com/s",params=kv)
    print(r.request.url)
    r.raise_for_status()
    print(len(r.text))
except:
    print("爬取失败")

1.3.4网络图片的爬取与存储

网络图片链接的格式:http://www.example.com/picture.jpg

http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg

import requests
import os#引入os库
url = "http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg"
root =  D://pics//"#文件的目录
path = root +url.split('/')[-1]#文件的目录加上jpg文件最后一部分,文件名称和网络图片名称相同
try:    
    if not os.path.exists(root):#判断根目录是否存在
        os.mkdir(root)
    if not os.path.exists(path):#判断文件是否存在
        r = requests.get(url)
        with open(path,'wb') as f:#wb图片为二进制文件
            f.write(r.content)
            f.close()
            print("文件保存成功")
    else:
        print("文件已存在")  
except:
    print("爬取失败")

类似的url,网上的视频、图片、动画、flash都可以用这个框架爬取

1.3.5 IP地址归属地的自动查询

比如某一个IP地址是来自北京,上海还是?怎么查询一个地址的归属,一个ip138的网站 http://www.ip138.com/ 提供人查询。

用python程序判断:

http://m.ip138.com/ip.asp?ip=ipaddress url接口,通过提交ip地址到前面这个网页获取归属地

import requests
url = "http://m.ip138.com/ip.asp?ip="
try:
    r = requests.get(url+'202.204.80112')#北京理工大学教育网的IP地址
    r.raise_for_status()
    r.encoding = r.apparent_encoding
    print(r.text[-500])
except:
    print("爬取失败")

2 网络爬虫的“盗亦有道”

2.1网络爬虫的尺寸

小规模数据量较小,爬取数据不敏感, Requests库 中规模,数据规模较大,爬取速度敏感 Scrapy库 大规模,搜索引擎,爬取速度关键 定制开发
爬取网页,玩转网页 爬取网站,爬取系列网站 爬取全网

2.2网络爬虫引发的问题

骚扰问题、法律风险、泄露隐私

2.3网络爬虫的限制

*来源审查:判断User-Agent进行限制

*发布公告:Robots协议

2.4Robots协议

2.4.1Robots协议基本语法

robots.txt(符合Robots 协议 (又称:爬虫协议、机器人协议等,全称:“网络爬虫排除标准”))是爬虫访问目标网站时查看的第一个文件,他会限定网络爬虫的访问范围。如果文件存在,则爬虫会按照该文件的内容确定访问的范围,否则,爬虫能访问所有没有密码保护的页面。

#注释:*代表所有,/代表根目录

User-Agent: *

Disallow: /

记录 作用
User-Agent 描述搜索引擎(爬虫)的名字,至少一个。若其值为“ * ”,则表示该协议对任何搜索引擎都有效,且这样的记录只有一条
Disallow 描述不希望被访问的URL,可以是完整路径,也可以是部分路径。任何一条该类记录为空,说明该网站的所有部分都可访问。在robots.txt文件中,至少有一条该类记录
Allow 描述希望被访问的URL,与 Disallow 类似。一个网站的所有 URL 默认Allow,所以通常与 Disallow 搭配使用,实现允许访问已备份网页的同时,禁止访问其他所有 URL 的功能

2.4.2Robots协议的理解

类人行为可以不参考Robots协议

3 解析HTML页面信息标记与提取方法 Beautiful Soup

3.1 beautifu souo(美味汤)对html进行解析,并提取相关信息。

页面网址:https://python123.io/ws/demo.html

from bs4 import BeautifulSoup
soup = BeautifulSoup('

data

','html.parser') #第一个参数表述,解析的东西,第二个参数表示传递html解析器

3.2Beautiful Soup (bs4)库的理解

解析、遍历、维护“标签树”的功能库

将标签树转换为BeautifulSoup类

3.2.1Beautiful Soup库解析器

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

3.3.获取tag标签内容,名字,属性

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo,"html.parser")
print(soup.title)
tag = soup.a#定义一个标签获取a标签的内容
print(tag)
#获取标签名字
print(soup.a.name)
print(soup.a.parent.name)#同过标签.name的方式获取其名字
#获取标签的属性
tag = soup.a
print(tag.atts)
print(tag.attrs['class'])#获得a标签class属性的值
print(tag.attrs['href'])#获得a标签链接属性的值
#获取标签之间的字符串信息
print(soup.a.string)
print(soup.p.string)
#获取注释
newsoup = BeautifulSoup("")
print(newsoup.p.string)

3.4基于bs4库的遍历方法

3.4.1标签树的下行遍历

属性 说明
.content 子节点列表,将标签所有儿子节点存入列表
.children 子节点的迭代类型,与.content类似,用于循环遍历儿子节点
.descendants 子孙节点的迭代类型,包含所有的子孙节点
for chlid in soup.body.children:#遍历儿子节点
    print(child)
for child in soup.body.children:#遍历子孙节点
    print(child)

3.4.2标签树的上行遍历

属性 说明
.parent 节点的父亲标签
.parents 节点先辈标签的迭代类型,用于循环遍历先辈节点

3.4.3标签树的平行遍历

属性 说明
.next_sibling 返回按照HTML文本顺序的下一个平行节点标签
.previous_sibling 返回按照HTML文本顺序的上一个平行节点标签
.next_sibling 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_sibling 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签
for sibling in soup.a.next_siblings:#遍历后续节点
    print(sibling)
    
    
for sibling in soup.a.previous_siblings:#遍历前续节点
    print(sibling)

3.5基于bs4库的HTML格式输出

如何让HTML内容更加友好的显示?

输出美化:prettify()方法

通常BeautifulSoup解析得到的Beautifulsoup对象格式较杂乱,可在输出时使用 **prettify() **方法对BeautifulSoup对象进行美化(为标签和内容添加换行符和缩进,以便于更友好直观地显示HTML内容),示例如下:

print(soup.prettify())

4 信息组织与提取

4.1信息标记形式

4.1.1 XML :eXtensible Markup Language

XML尖括号、标签表达信息的标记形式(html属于XML)

最早的标记语言,相当繁琐

Internet上的信息交互与传递

4.1.2 JSON : JavaScript Object Notation

JSON 有类型的键值对标记

信息有类型,适合程序处理,较XML简洁

移动云端和节点的信息通信,无注释

4.1.3 YAML :YAML Ain’t Markup Language

无类型的键值对标记

信息无类型,文本信息比例最高,可读性非常好

各类系统的配置文件,有注释且移动

4.2信息组织与提取方法

方法一:完整解析信息的标记形式,再提取关键信息

解析格式   XML JSON YAML?
需要标记解析器  例如:bs4
优点:信息解析准确
缺点:提取过程繁琐,速度慢

方法二:无视标记形式,直接搜索关键信息

搜索
对信息文本查找函数即可
优点:提取过程简洁,速度较快
缺点:提取结果准确性与信息内容相关

实例:提取HTML中所有的URL标签

如何提取融合方法一方法二

思路:1)搜索到所有的标签

​ 2)解析标签格式,提取href后的链接内容·。

from bs4 import BeaytifulSoup
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all('a'):
    print(link.get('href'))
#http://www.icourse163.org/course/BIT-268001
#http://www.icourse163.org/course/BIT-1001870001

4.3基于bs4库的HTML内容的查找方法

网页中的信息都存在于网页的文本或者各种不同标签的属性值,为获得这些有用的网页信息,可通过一些查找方法获取文本或标签属性。bs4 库内置一些查找方法,其中最常用的两个方法功能如下:

方法 功能
find() 查找符合查询条件的第一个标签节点
find_all() 查找所有符合查询条件的标签节点,并返回一个列表

这两个方法的参数相同,以find_all() 为例,介绍该方法中参数的作用,find_all() 定义如下:

find_all(self,name=Nobe,attrs={key:value},recursive=True,text=None,limit=None,**kwargs)

上述方法中的一些重要参数含义如下:

4.1. name 参数

查找所有名字为name的标签,但**‘name=’**字符串会被忽略.以下是name参数的几种情况:

传入字符串

在搜索的方法中传入一个字符串,BeautifulSoup 对象会查找与字符串完全匹配的内容.例如:

soup.find_all('b') #查找文档中所有的标签
​```###### 1.2 传入正则表达式
如果传入一个正则表达式,那么BeautifulSoup对象会通过re模块的match()函数进行匹配.例如:
​```python
soup.find_all(re.compile("^b"))#使用正则表达式匹配所有以字母b开头的标签
​```###### 1.3 传入列表
如果传入一个列表,那么BeautifulSoup对象将会与列表中任意元素匹配的内容返回.例如:

soup.find_all([“a”,“b”]) #返回文档中所有标签和标签

如果某个指定名字的参数不是搜索方法中内置的参数名,那么在进行搜索时,会把该参数当作指定名字的标签中的属性搜索.例如:
​```python
soup.find_all(id='link2')#在find_all()方法中传入名称为id,值为link2的参数,此时BeautifulSoup对象会搜索每个标签的属性

若传入的参数属于Python保留字(如: class),可以在保留字后添加一条下划短线.例如:

soup.find_all(class_='sister')

4.2attrs参数

对标签属性值的检索字符串,可标注属性检索

soup.find_all('p','course')#查找p标签中包含course字符串的信息
soup.find_all(id='link1')#对属性做相关的约定,查找属性为link1的元素

若传入多个指定名字的参数,则可同时过滤出标签中的多个属性.例如:

import re  #正则表达式库
soup.find_all(href=re.compile("elsie"),id='link1')

4.3recursive参数

是否对子孙全部检索,默认True

4.4string参数

标签之间的内容

soup.find_all(string = "Basic Python")#精确的输入字符串进行检索
#输出['Basic Python']
#如果只希望用python检索到更多的信息,则引入re正则表达式库
import re
soup.find_all(string = re.compile("python"))
#输出['This is a python demo page', 'The demo python introduces several python courses.']

4.5简短模式

(…)等价于.find_all(…)

soup(…)等价于soup.find_all(…)

5.实例中国大学排名爬虫

功能描述

输入:大学排名URL链接http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html

输出:大学排名信息的屏幕输出(排名,大学名称,总分)

技术路线:requests-bs4

定向爬虫:仅对输入url进行爬取,不扩展爬取

程序的结构设计
步骤1:从网络上获取大学排名网页内容
getHTMLText()
步骤2:提取网页内容中信息到合适的数据结构
fillUnivList()
步骤3:利用数据结构展示并输出结果
printUnivList()

二维的数据结果,采取列表的方式

写结构框架

import requests
from bs4 import BeautifulSoup
import bs4
def getHTMLText(url):
    return ""
def fillUnivList(ulist,html):
    pass#不做任何操作
def printUnivList(ulist,num):
    print("Suc" + str(num))
def main():
    uinfo = []
    url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html '
    html = getHTMLText(url)
    fillUnivList(uinfo,html)
    printUnivList(uinfo,20)#20 univs
main()

所要提取信息的源代码html,观察

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 fillUnivList(ulist,html):
    soup = BeautifulSoup(html,"html.parser")
    for tr in soup.find('tbody').children:#tr没一所大学对应的信息
        if isinstance(tr,bs4.element.Tag):#检测tr标签类型,过滤掉非标签类型
            tds = tr('td')#找到td标签
            ulist.append([tds[0].string,tds[1].string,tds[3].string])
            #把我们需要的td标签加到列表中    
    pass#不做任何操作
def printUnivList(ulist,num):
    print("{:^10}\t{:^6}\t{:^10}".format("排名","学校名称","总分"))
    for i in range(num):
        u=ulist[i]
        print("{:^10}\t{:^6}\t{:^10}".format(u[0],u[1],u[2])
    print("Suc" + str(num))

第一次运行错误出现输出错误

 print("(:^10)\t(:^6)\t(:^10)".format("排名","学校名称","总分"))
 #花括号写成了括号

正确输出结果

查询python花括号{}的用法:https://blog.csdn.net/qq_35736437/article/details/90052253

代表dict字典数据类型,字典是Python中唯一内建的映射类型。字典中的值没有特殊的顺序,但都是存储在一个特定的键(key)下。键可以是数字、字符串与元祖。

示例

dic = {‘jay’:‘boy’,‘may"’:‘girl’}
dic
{‘jay’: ‘boy’, ‘may’: ‘girl’}
————————————————
原文链接:https://blog.csdn.net/qq_35736437/article/details/90052253

中文对齐问题的解决

当中文字符宽度不够时,采用西文字符填充;中西文字符占用宽度不同

采用中文字符的空格填充chr(12288)

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

正确输出

6 正则表达式库(re)入门

正则表达式 regular expression        regex   RE
优势:简洁,一行胜千言
re库是Python的标准库,主要应用于字符串匹配表达中,由字符和操作符构成,调用方法import re
正则表达式的表示类型:
    raw string 类型(原生字符串类型:不包含转义符/的字符串)
    re库采用raw string类型表示正则表达式,表示为:r'text'
    例如:r'[1-9]\d{5}'

re*(支持正则表达式)模块一般使用步骤:

(1) 使用compile() 函数将正则表达式以字符串形式编译为一个Pattern 类型的对象。

(2) 通过Pattern 对象提供的一系列方法对文本进行查找或替换,得到一个处理结果。

(3) 使用处理结果提供的属性和方法获取信息,如匹配到的字符串。

正则表达式关于中文的匹配

大多数情况下,从网站爬取的网页源码都会有汉字,如果要匹配这些汉字,就需要知道其对应的正则表达式,通常情况下,中文对应的Unicode编码范围为**[u4e00-u9fa5a]** 这个范围不包括全角(中文)标点,但大多数情况是可以使用的。

6.1正则表达式常见字符及其含义

https://tool.oschina.net/uploads/apidocs/jquery/regexp.html

操作符 说明 实例
. 表示任何单个字符
[] 字符集,对单个字符给出取值范围 [abc]表示a,b,c[a-z]表示a到z单个字符
[^] 非字符集,对单个字符给出排除范围 [^abc]表示非a或b或c的单个字符
* 前一个字符0次或无限次扩展 abc*表示ab,abc,abcc等
+ 前一个字符1次或无限次扩展 abc+表示abc,abcc,abccc等
? 前一个字符0次或1次扩展 abc?表示ab,abc
| 左右表达式任意一个 abc|def表示abc,def
{m} 扩展前一个字符m次 ab{2}c表示abbc
{m,n} 扩展前一个字符m至n次(含n) ab{1,2}c表示abc,abcc
^ 匹配字符串开头 ^abc表示abc且在一个字符串的开头
$ 匹配字符串结尾 abc$表示一个字符串的结尾
() 分组标记,内部只能使用|操作符 (abc)表示abc,(abc|def)表示abc,def
\d 数字,等价于[0-9]
\w 单词字符,等价于[A-Za-z0-9_]

6.2正则表达式语法实例

正则表达式 对应字符串
P(Y|YT|YTH|YTHO)?N ‘PN’,‘PYN’,‘PYTN’,‘PYTHN’,‘PYTHON’
PYTHON+ ‘PYTHON’,‘PYTHONN’,‘PYTHONNN’…
PY[TH]ON ‘PYTON’,‘PYTHON’
PY[^TH]?ON ‘PYON’,‘PYaON’,‘PYbON’,‘PYcON’…
PY{:3}N ‘PN’,‘PYN’,‘PYYN’,‘PYYYN’

6.3正则表达式编译标志及其含义

匹配模式常用在编译正则表达式时,作用涉及 区分大小写、忽略非法字符等。

正则表达式的模式时可以同时使用多个的,在Python里使用 | 同时添加多个模式

匹配模式flages 说明
re.I 忽略大小写
re.L 字符集本地化,该功能是为了支持多语言版本的字符集使用环境。比如‘\w’在英文环境下,代表匹配字母数字,但在法语环境下,缺省设置导致不能匹配法语字符,加上该选项就可匹配。但该选项仍对中文不友好,不能匹配中文字符。
re.M 多行模式,改变 ^ 和 $ 的行为
re.S 点任意匹配模式,此模式下,‘.’的匹配不受限制,可匹配包括换行符在内的任何字符
re.X 冗余模式(详细模式),此模式忽略正则表达式中的空白字符和#的注释(注释与表达式可多行书写)
re.U 使用\w,\W,\b,\B 这些元字符时将按照Unicode定义的属性

6. 正则表达式常用函数

函数 用法详解
re.compile(pattern,flags=0) 该方法通常用作以下其他方法的基础。给定一个正则表达式pattern,默认flag = 0,表示不使用任何模式。
re.match(pattern,string,flags=0) 从给定字符串起始位置进行匹配,匹配成功则返回匹配结果<_sre.SRE_Match object;span=(0,匹配成功的子串在字符串中的结束位置),match=‘[匹配的子串]’>否则返回None
re.search(pattern,string,flags=0) 扫描整个字符串返回第一个匹配成功的结果
re.findall(pattern,string,flags=0) 扫描整个字符串,以列表的形式返回所有匹配成功的结果
re.split(pattern,string,maxsplit=0,flag=0) 使用pattern寻找切分字符串的位置,返回包含切分后子串的列表,若匹配不到,则返回包含原字符串的一个列表。maxsplit 最大分割数
re.sub(pattern,repl,string,count=0,flags=0) 替换函数,将正则表达式pattern匹配到的子串替换为repl指定的字符串,count 用于指定最大替换次数
fre.finditer() 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象

其他函数参考:https://www.cnblogs.com/dyfblog/p/5880728.html

6.4Re库的另一种等价用法

rst = re.search(r'[1-9]\d{5},'BIT 10086')
#函数式用法:一次性操作
#面向对象用法:编译后的多次操作。好处,多次使用可以加快程序运行
#regex = re.compile(pattern,flags=0)将正则表达式字符串形式编译成正则表达式对象,
regex = re.complie(r'[1-9]\d{5}')
rst = regex.search('BIT 10081')

6.5Re库的Match对象(一次匹配的结果)

Match对象的属性

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

Match对象的方法,详见6.6

方法 说明
.group(0) 获得匹配后的字符串
.start() 匹配字符串在原始字符串的开头位置
.end() 匹配字符串在原始字符串的结束位置
.spand() 返回(.start(),.end())
>>>import re
>>>m = re.search(r'[1-9]\d{5}','BIT10081 TSU100084')
>>>m.string 
'BIT10081 TSU100084'
>>>m.re
re.compile('[1-9]\d{5}')
>>>m.pos
0
>>>m.group(0)#返回的是第一次匹配的结果,finditer()返回全部
'100081'
>>>m.span()
(3,9)
>>>m.start()
3

贪婪匹配

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

>>>match = re.search(r.'PY.*
N','PYANBNCNDN')
>>>match.group(0)
'PYANBNCNDN'

如何输出最小匹配?在操作符后面增加一个问号

最小匹配操作符

操作符 说明
*? 前一个字符0次或无限次扩展,最小匹配
+? 前一个字符1次或无限次扩展,最小匹配
?? 前一个字符0次或1次扩展,最小匹配
{m,n}? 扩展前一个字符m至n次(含n),最小匹配

6.6 正则表达式常用方法

方法 说明
group([group1,group2….]) 获得一个或多个分组截获的字符串;指定多个参数时将以元组的形式返回。group1可使用编号或者别名,默认返回group(0),即整个匹配的子串。没有截获字符串的组返回None
groups([default]) 以元组的形式返回全部分组接获的字符串。相当于调用group(1,2,…last),default表示没有接货字符串德祖以这个值替代,默认为None
groupdict([default]) 返回以有别名的组的别名为键,以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上
end([group]) 返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1).group默认为0
start([group]) 返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认为0
span([group]) 返回(start(group),end(group))
expand(template) 将匹配到的分组带入template中饭后返回。template可使用\id或\g、\g引用分组,但不能使用编号0.\id与\g等价,但\10将被认为是第10个分组,如果想表达\1之后是字符‘0’,只能使用\g<1>0

关于正则表达式更完整内容:https://www.cnblogs.com/dyfblog/p/5880728.html

正则表达式Python官方文档:https://docs.python.org/2/howto/regex.html#compiling-regular-expressions

正则表达式30分钟教程:https://www.jb51.net/tools/zhengze.html

7 淘宝商品比价定向爬虫实例

功能描述

目标:获取淘宝搜索页面的信息,提取其中的商品,提取其中的商品名称和价格。

理解:淘宝的搜索接口

​ 翻页的处理

技术路线:requests-re

观察接口

定向爬虫可行性,淘宝搜索页面不允许任何爬虫访问,如果个人对淘宝具有相同的频率,不要不加限制的爬取这个网占是可行的

程序的结构设计

步骤1:提交商品搜索请求,循环获取页面。

步骤2:对于每个页面,提取商品名称和价格信息。

步骤3:将信息输出到屏幕上。

写框架

import requests
import re

def getHTMLText(url):
    print("")
def parsePage(ilt,html):
    print("")
def printGoodsList(ilt):
    print("")
def main():
    goods = '书包'
    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 = def getHTMLText(url)
            getHTMLText(infoList,html)
        except:
            continue
        printGoodsList(infoList)
main()

写函数内容

通过观察网页源代码,发现任何商品的价格有一个raw_price字段来标识,而商品名字用raw_title字段标识

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])#eval函数将所获得字符中的双引号和单引号去掉
            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 = 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)
main()

8股票数据定向爬虫

具体可点击链接 https://blog.csdn.net/CJX_up/article/details/77912510

功能描述

目标:获取上交所和深交所所有股票的名称和交易信息

输出:保存到文件中

技术路线:requests-bs4-re

候选数据网站的选择

新浪股票:http://finance.sina.com.cn/stock/

百度股票:https://gupiao.baidu.com/stock/

选取原则:股票信息静态存在于HTML页面中,非JS代码生成,没有Robots协议限制。

选取方法:游览器F12,源代码查看等

程序的结构设计:

步骤1:从东方财富网获取股票列表

步骤2:根据股票列表逐个到百度股票获取个股信息

步骤3:将结果存储到文件

import requests
from bs4 import BeautifulSoup
import traceback
import re

def getHTMLText(url,code='utf-8'):
    try:
        r = requests.get(url,timeout = 30)
        r.raise_for_status()
        r.encoding = code
        return r.text
    except:
        return ""
def getStockList(lst,stockURL):#从东方财富网获得股票的信息列表
    html = getHTMLText(stockURL,'GB2312')
    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])#以s开头中间是h或z字符,后面有6个数
        except:
            continue
def getStockInfo(lst,stockURL,fpath):#获得每一支各股的股票信息,并存入文件
    count = 0
    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':'bots-name'})[0]
            infoDict.update({'股票名称':name.text.split()[0]})#使用split分割
            
            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')
                count = count + 1
                print('\r当前速度:{:.2f}%'.format(count*100/len(lst)),end='')
        except:
            count = count + 1
            print('\r当前速度:{:.2f}%'.format(count*100/len(lst)),end='')
            traceback.print_exc()
            continue
    return ""
def main():
    stock_list_url = 'http://quote.eastmoney.com/stocklist'
    stock_info_url = 'https://gupiao.baidu.com/stock/'
    output_file = 'D://BaiduStockInfo.txt'
    alist = []
    getStockList(alist,stock_list_url)
    getStockInfo(alist,stock_info_url,output_file)
main()

展示动态显示不换行进度条\r

count = count + 1
print('\r当前速度:{:.2f}%.format(count*100/len(lst)),end='')

9 Scrapy爬虫框架

详细内容请点击 https://blog.csdn.net/hxxjxw/article/details/90572756

scrapy 不是一个函数功能库,而是一个爬虫框架

爬虫框架是实现爬虫功能的一个软件结构和功能组件集合。

爬虫框架是一个半成品,能够帮助用户实现专业网络爬虫。

Engine:

不需要用户修改。控制所有模块之间的数据流,根据条件触发事件

Downloader:

根据请求下载网页,不需要用户进行修改

Scheduler:

对所有爬虫请求进行调度管理,不需要用户修改

Downloader Middleware:

目的:实施Engine、Scheduler和Downloader之间进行用户可配置的控制

功能:修改、丢弃、新增请求或响应

Spider:

解析Downloader返回的响应(Response)

产生爬取项(scraped item)

产生额外爬取请求(Request)

Item Pipelines:

以流水线的方式处理Spider产生的爬取项。

由一组操作顺序组成,类似流水线,每个操作是一个Item Pipeline类型。

可能操作包括:清理、检验和查重爬取项中的HTML数据、将数据存储到数据库。

Spider Middleware:

目的:对请求和爬取项的再处理

功能:修改、丢弃、新增请求或爬取项

详细介绍:

  • 引擎(Engine)
    用来处理整个系统的数据流处理, 触发事务(框架核心)

  • 调度器(Scheduler)
    用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

  • 下载器(Downloader)
    用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的

  • 爬虫(Spiders)
    爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面

  • 项目管道(Pipeline)
    负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

  • 下载器中间件(Downloader Middlewares)
    位于Scrapy引擎和下载器之间的框架,实施Engine、Scheduler和Downloader之间进行用户可配置的控制。修改、丢弃、新增请求或响应。

  • 爬虫中间件(Spider Middlewares)
    介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。

  • 调度中间件(Scheduler Middewares)
    介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

requests vs scrapy

requests Sceapy
页面级爬虫 网站级爬虫
功能库 框架
并发性考虑不足,性能较差 并发性好,性能较高
重点在于页面下载 重点在于爬虫结构
定制灵活 一般定制灵活,深度定制困难
上手十分简单 入门较难

Scrapy常用命令

命令 说明 格式
startproject 创建一个新工程 scrapy startproject[dir]
genspider 创建一个爬虫 scrapy genspider[options]
settings 获得爬虫配置信息 scrapy setting[options]
crawl 运行一个爬虫 scrapy crawl
list 列出工程中所有爬虫 scrapy list
shell 启动URL调试命令 scrapy shell [url]

为什么Scrapy采用命令行创建和运行爬虫?

命令行(不是图形界面)更容易自动化,适合脚本控制

本质上,Scrapy是给程序员使用的,功能(而不是界面)更重要

scrapy爬虫的基本使用

步骤一:采用命令行生成一个工程

输入scrapy startproject python123demo

生成的工程目录

python123demo/ :外层目录

​ scrapy.cfg :部署scrapy爬虫的配置文件

​ python123demo/ :Scrapy框架的用户自定义python代码

—init—.py :初始化脚本

​ items.py :Items代码模块(继承类)

​ middleware.py :Middlewares代码模块(继承类)

​ pipelines.py: Pipelines代码模板(继承类)

​ settings.py :Scrapy的配置文件

​ spiders/: Spiders代码模板目录(继承类)

​ —init—.py: 初始文件,无需修改

​ —pycache—/: 缓存目录无需修改

步骤二:在工程中产生一个Scrapy爬虫

打开命令行输入命令scrapy genspider demo python123.io,生成一个爬虫

demo.py文件

import scrapy

class DemoSpider(scrapy.Spider):
    name = 'demo'#当前爬虫名字叫demo
    allowed_domains = ['python123.io']#只能爬取这个域名以下的相关链接
    start_urls = ['http://python123.io/']#Scrapy框架所能爬取的初始页面

    def parse(self, response):
        pass
   # parse()用于处理响应,解析内容成字典,发现新的URL爬取请求。

步骤三:配置产生的spider爬虫

修改demo.py文件让它能够按照我们的要求访问链接,并爬取。

import scrapy
class DemoSpider(scrapy.Spider):
    name = 'demo'
    #allowed_domains = ['python123.io']
    start_urls = ['http://python123.io/ws/demo.html']

    def parse(self, response):
        fname = response.url.split('/')[-1]
        with open(fname,'wb') as f:
            f.write(response.body)
        self.log('Saved file %s.' %name)
        pass

步骤四:运行爬虫,获取网页。

命令行下执行scrapy crawl demo

yield关键字

yield----生成器

生成器是一个不断产生值的函数

包含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

10 scrapy爬虫的使用步骤

步骤1:创建一个工程和Spider模板

步骤2:编写spider

步骤3:编写Item Pipeline

步骤4:优化配置策略

Scrapy爬虫的数据类型

Request类

requests对象表示一个HTTP请求

属性或方法 说明
.url requests对应的请求URL地址
.method 对应的请求方法,‘GET’ 'POST’等
.headers 字典类型风格的请求头
.body 请求内容主体,字符串类型
.meta 用户添加的扩展信息,在scrapy内部模块间传递信息
.copy() 复制该请求

Response类

属性或方法 说明
.url response对应的url地址
.status http状态码,默认是200
.hesders response对应的头部信息
.body response对应得内容信息,字符串类型
.flags 一组标记
.request 产生resonse类型对应的request对象
.copy() 复制该响应

Item类

item对象表示从HTML页面中提取的信息内容

由spider生成,由item pipeline处理

item类似字典类型,可以按照字典类型操作

Scrapy爬虫支持多种HTML信息提取方法

Beautiful Soup
lxml
re
XPath Selector
CSS Selector

css selector的基本使用

.css('a::attr(href)').extract()
#a:标签名称  href:标签属性

实例:股票数据scrapy爬虫

步骤1:建立工程和spider模板

\>scrapy startproject BaiduStocks
\>cd BaiduStocks
\>scrapy genspider stocks baidu.com
进一步修改spider/stocks.py文件

步骤2:编写Spider

*配置stock.py文件
*修改对返回页面的处理
*修改对新增URL爬取请求的处理

spider

# -*- coding: utf-8 -*-
import scrapy

class StocksSpider(scrapy.Spider):
    name = 'stocks'
    allowed_domains = ['baidu.com']
    start_urls = ['http://baidu.com/']

    def parse(self, response):
        pass

修改后

详情点击 https://www.cnblogs.com/douzujun/p/12249226.html

或者 https://www.jianshu.com/p/be3024c86c4c

esders | response对应的头部信息 |
| .body | response对应得内容信息,字符串类型 |
| .flags | 一组标记 |
| .request | 产生resonse类型对应的request对象 |
| .copy() | 复制该响应 |

Item类

item对象表示从HTML页面中提取的信息内容

由spider生成,由item pipeline处理

item类似字典类型,可以按照字典类型操作

Scrapy爬虫支持多种HTML信息提取方法

Beautiful Soup
lxml
re
XPath Selector
CSS Selector

css selector的基本使用

.css('a::attr(href)').extract()
#a:标签名称  href:标签属性

实例:股票数据scrapy爬虫

步骤1:建立工程和spider模板

\>scrapy startproject BaiduStocks
\>cd BaiduStocks
\>scrapy genspider stocks baidu.com
进一步修改spider/stocks.py文件

步骤2:编写Spider

*配置stock.py文件
*修改对返回页面的处理
*修改对新增URL爬取请求的处理

spider

# -*- coding: utf-8 -*-
import scrapy

class StocksSpider(scrapy.Spider):
    name = 'stocks'
    allowed_domains = ['baidu.com']
    start_urls = ['http://baidu.com/']

    def parse(self, response):
        pass

修改后

详情点击 https://www.cnblogs.com/douzujun/p/12249226.html

或者 https://www.jianshu.com/p/be3024c86c4c

你可能感兴趣的:(笔记,网络爬虫,爬虫)