Python网络爬虫与信息提取

Python网络爬虫与信息提取,第1张

概述文章目录单元一Requests库HTTP协议及Requests库方法Requests库get()方法Requests库的安装Requests主要方法爬取网页的通用代码框架Robots协议robots协议遵守方式网络爬虫引发的问题京东商品页面的爬取百度/360搜索关键词提交网络图片的爬取和存储IP地址归属地的自动查询

文章目录单元一 Requests库HTTP协议及Requests库方法Requests库get()方法Requests库的安装Requests主要方法爬取网页的通用代码框架Robots协议robots协议遵守方式网络爬虫引发的问题京东商品页面的爬取百度/360搜索关键词提交网络图片的爬取和存储IP地址归属地的自动查询BeautifulSoup库安装Beautiful Soup库的基本元素基于bs4库的HTML格式输出基于bs4库的HTML内容遍历方法基于bs4库的HTML内容查找方法三种信息标记形式的比较提取信息的一般方法中国大学排名定向爬虫Re库的match对象Re库的基本使用Re库的贪婪匹配和最小匹配正则表达式概念正则表达式的语法淘宝商品比价定向爬虫股票数据定向爬虫requests库和Scrapy爬虫比较Scrapy爬虫的常用命令Scrapy爬虫框架介绍Scrapy爬虫框架解析Scrapy实例1Scrapy爬虫的基本使用yield关键字的使用股票数据Scrapy爬虫实例

单元一 Requests库http协议及Requests库方法


http协议:Hypertext Transfer Protocal,超文本传输协议,基于响应与请求、无状态的应用层协议

http协议采用URL作为定位网络资源的标识

每个URL格式:http://host[:port][path]
host:一个合法的Internet主机域名或IP地址
port:端口号,缺省为80
path:请示资源的路径
URL通过http协议存取资源的Internet路径,一个URL对应一个资源

http协议方法:



PATCH和PUT的区别:
若URL有一组数据UserInfo,包含UserID、Username等20个字段,要修改Username,其他不变,PATCH仅向URL提交Username的局部更新请示,PUT必须要提交所有字段,未提交的字段被删除。所以PATCH方法可以节省带宽


Requests库的post()方法

payload = {'key1':'value1','key2':'value2'}r = requests.post('http://httpbin.org/post',data = payload)print(r.text)

键值对默认存到表单下

r = requests.post('http://httpbin.org/post',data = 'ABC')print(r.text)

字符串自动编码为data
put()方法会覆盖原有的数据

Requests库get()方法
url = 某个网址r = requests.get(url)

request()构造一个向服务器请求资源的Requests对象
Response返回一个包含服务器资源的Requests对象

requests.get(url,params=None,**kwargs)

url:拟获取页面的url链接
params:url中的额外参数,字典或字节流格式,可选
**kwargs:12个控制访问的参数
Requests库共有7个常用方法,除了requests()方法为基础方法外,其他方法都是调用requests()方法

import requestsr = requests.get("http://www.baIDu.com")print(r.status_code)type(r)r.headers

状态码为200表示成功
Response对象的属性


import requestsr = requests.get("http://www.baIDu.com")r.status_coder.enCodingr.apparent_enCodingr.enCoding = 'utf-8'r.text

如果header中不存在charset,enCoding则认为编码为ISO-8859-1,它不能解析中文

Requests库的安装

cmd控制台:pip install requests

Requests主要方法
requests.request(method,url,**kwargs)

method:请求方法,如get/put/OPTIONS等7种
url:链接
**kwargs:控制访问参数,13个

r = requests.request('GET',url,**kwargs)r = requests.request('head',url,**kwargs)r = requests.request('POST',url,**kwargs)r = requests.request('PUT',url,**kwargs)r = requests.request('PATCH',url,**kwargs)r = requests.request('delete',url,**kwargs)r = requests.request('OPTIONS',url,**kwargs)

**kwargs:
params:字典或字节序列,作为参数增加到url中

kv = {'key1':'value1','key2':'value2'}r = requests.request('GET','http://python123.io/ws',params=kv)print(r.url)

data:字典、字节序列或文件对象,作为Request的内容

kv = {'key1':'value1','key2':'value2'}r = requests.request('GET','http://python123.io/ws',data=kv)body ='主体内容'r = requests.request('POST','http://python123.io/ws',data = body)

Json:JsON格式的数据,作为Reuqest的内容

kv = {'key1':'value1'}r = requests.request('POST','http://python123.io/ws',Json= kv)

headers:字典,http定制头

hd={'user-agent':'Chrome/10'}r = requests.request('POST','http://python123.io/ws',headers= hd)

cookies:字典或cookieJar,Request中的cookie
auth:元组,支持http认证
files:字典类型,传输文件

fs = {'file':open('data.xls', 'rb')}r = requests.request('POST','http://python123.io/ws',files= fs)

timeout:设定超时时间,以秒为单位

r = requests.request('GET','http://python123.io/ws',timeout=10)

proxIEs:字典类型,设定访问代理服务器,可以增加登录认证

pxs = {'http':'http://user:pass@10.10.10.1:1234'		'https':'https://10.10.10.1:4321'}r = requests.request('GET','http://www.baIDu.com',proxIEs=pxs)

allow_redirects:True/False,默认为True,重定向开关
stream:True/False,默认为True,获取内容立即下载开关
verify:True/False,默认为True,认证SSL证书开关
cert:本地SSL证书路径

requests.get(url,params=None,**kwargs)

**kwargs:12个参数,即request中除了params外的其他参数

requests.head(url,**kwargs)

**kwargs:13个参数

requests.post(url,data=None,Json=None,**kwargs)

data:字典、字节序列或文件,Request的内容
Json:JsON格式的数据,Request的内容
**kwargs:11个参数

requests.put(url,data=None,**kwargs)

data:字典、字节序列或文件,Request的内容
**kwargs:12个参数

requests.patch(url,data=None,**kwargs)

data:字典、字节序列或文件,Request的内容
**kwargs:12个参数

requests.delete(url,**kwargs)

**kwargs:13个参数

爬取网页的通用代码框架

Requests库的异常


import requestsdef geHTMLText(url):    try:        r = requests.get(url,timeout=30)        r.raise_for_status()        r.enCoding = r.apparent_enCoding        return r.text    except:        return "产生异常"if __name__ == "__main__":    url = "http://www.baIDu.com"    print(getHTMLText(url))
Robots协议

Robots Exclusion Standard 网络爬虫排除标准
robots.txt在网站的根目录下

*表示所有

disallow: /?*表示所有都不允许访问以?开头的路径

disallow:/pop/*.HTML表示所有都不允许访问pop下的所有HTML

User-agent:EtaoSpIDer
disallow: /
表示EtaoSpIDer不允许爬取任何内容

如果一个网址不提供robots协议,则默认允许所有爬虫爬取

robots协议遵守方式

robots协议是建议但非约束性,不遵守存在法律风险

类人行为可不参考Robots协议,访问量非常小,速度慢

网络爬虫引发的问题

小规模,可用requests库
中规模,数据规格大,速度敏感,可用Scrapy
爬取全网,如搜索引擎,定制开发

网络爬虫的骚扰,服务器崩溃

服务器上的数据有产权归属

爬虫泄露隐私

爬虫限制:
来源审查:判断User-agent
robots协议:告示牌

京东商品页面的爬取
import requestsurl = "https://item.jd.com/2967929.HTML"try:    r = requests.get(url)    r.raise_for_status()    r.enCoding = r.apparent_enCoding    print(r.text[:1000])except:    print("爬取失败")
百度/360搜索关键词提交
import requestskeyword = "Python"try:    kv = {'wd':keyword}    r = requests.get("http://www.baIDu.com/s",params =kv)    print(r.requests.url)    r.raise_for_status()    print(len(r.text))except:    print("爬取失败")
网络图片的爬取和存储
import requestsimport osurl = "http://image.nationalgeographic.com.cn/2017/0211/20170211061910157.jpg"root ="D://pics//"path = root + url.split('/')[-1]try:    if not os.path.exists(roo):        os.mkdir(root)    if not os.path.exists(path):        r = requests.get(url)        with open(path,'wb') as f:            f.write(r.content)            f.close()            print("文件保存成功")    else:        print("文件已存在")except:    print("爬取失败")
IP地址归属地的自动查询
import requestsurl = "http://m.ip138.com/ip.asp?ip="try:    r = requests.get(url+'202.204.80.122')    r.raise_for_status()    r.enCoding = r.apparent_enCoding    print(r.text[-500:])except:    print("爬取失败")
BeautifulSoup库安装

cmd下,输入pip install beautifulsoup4

HTML的格式
<HTML>
<head></head>
<body>
<\body>
</HTML>

import requestsfrom bs4 import BeautifulSoupr = requests.get("http://python123.io/ws/demo.HTML")r.textdemo = r.textsoup = BeautifulSoup(demo,"HTML.parser")print(soup.prettify())
Beautiful Soup库的基本元素

此库是解析、遍历、维护标签树的功能库

<p class=“Title”>…</p>
名称是p
属性是class=“Title”

解析器:


基本元素

from bs4 import BeautifulSoupsoup = BeautifulSoup(demo,"HTML.parser")soup.Titletag = soup.atag.attrstag.attrs['class']tag.attrs['href']type(tag.attrs)type(tag)soup.a.namesoup.a.parent.namesoup.a.parent.parent.namesoup.a.stringsoup.psoup.p.stringtype(soup.p.string)newsoup = BeautifulSoup("<b>--Tis is a comment</b><p>This is not a comment</p>","HTML.parser")newsoup.b.stringtype(newsoup.b.string)newsoup.p.stringtype(newsoup.p.string)
基于bs4库的HTML格式输出
from bs4 import BeautifulSoupsoup = BeautifulSoup(demo,"HTML.parser")soup.prettify()print(soup.prettify())
@L_419_52@基于bs4库的HTML内容遍历方法


标签树的下行遍历

soup = BeautifulSoup(demo,"HTML.parser")soup.headsoup.head.contentssoup.body.contentslen(soup.body.contents)soup.body.contents[1]

上行遍历

soup = BeautifulSoup(demo,"HTML.parser")soup.Title.parentsoup.HTML.parentsoup.parent

上行遍历

soup = BeautifulSoup(demo,"HTML.parser")for parent in soup.a.parents:	if parent is None:		print(parent)	else:		print(parent.name)

平行遍历


平行遍历发生在同一父节点下的各节点间

soup = BeautifulSoup(demo,"HTML.parser")soup.a.next_siblingsoup.a.next_sibling.next.siblingsoup.a.prevIoUs_siblingsoup.a.prevIoUs_sibling.prevIoUs_siblingsoup.a.parent
基于bs4库的HTML内容查找方法
<>.find_all(name,attrs,recursive,string,**kwargs)

返回一个列表类型,存储结果
name:对标签名称的检索字符串
attrs:对标签属性值的检索字符串,可标注属性检索
recursive:是否对子孙全部检索,默认是True
string:<>…</>中字符串区域的检索字符串

soup.find_all('a')soup.find_all(['a','b'])

若只给True,则返回所有标签

for tag in soup.find_all(True):	print(tag.name)
soup.find_all('p','course')

精准查找:

soup.find_all(ID='link1')

模糊查找:正则表达式

soup.find_all(string = "Basic Python")

简写:
<tag>()等价于<tag>.find_all()

扩展方法

三种信息标记形式的比较

XML:eXtensible MarkuP Language
用<>标记
<name>…</name>

JsON:JavaScript Object Notation
用有类型键值对标记
“key”:“value”
“key”:[“value1”,“value2”]
“key”:{“value1”,“value2”}

YAML:YAML Ain’t MarkuP Language
无类型键值对标记
firstname:xxx
lastname:XXX

XML:有效信息占比不高,大部分信息被标签占用,可用于Internet
JsON:比XML简洁,用于移动端或程序,无法体现注释
YAML:有效信息利用率最高,用于系统配置文件,有注释

提取信息的一般方法

一:完整解析后再提取关键信息
二:无视标记形式,直接搜索关键信息

from bs4 import BeautifulSoupsoup = BeautifulSoup(demo,"HTML.parser")for link in soup.find_all('a'):	print(link.get('href'))
中国大学排名定向爬虫
import requestsimport bs4from bs4 import BeautifulSoupdef 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:        if isinstance(tr,bs4.element.Tag):            tds = tr('td')            uList.append([tds[0].string,tds[1].string,tds[2].string])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]))def main():    uinfo = []    url = "http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.HTML"    HTML = getHTMLText(url)    fillUnivList(uinfo, HTML)    printUnivList(uinfo, 20)main()
Re库的match对象

Match对象是一次匹配的结果,有type(match)将返回<class ‘_sre.SRE_Mathc’>
Match对象的属性


Match对象的方法

import rem = re.search(r'[1-9]\d{5}','BIT10081 TSU100084')m.stringm.rem.posm.endposm.group(0)m.start()m.end()m.span()
Re库的基本使用

用于字符串匹配
raw string类型(原生字符串类型),表达为r’text’,它不包含转义符的字符串,比如\\仅用\表示

Re库主要功能函数

re.search(pattern,string,flags=0)

pattern:正则表达式字符串
string:待匹配的字符串
flags:正则表达式使用时的控制标记

import rem = re.search(r'[1-9]\d{5}','BIT 10081')if match:	print(match.group(0))
re.match(pattern,string,flags=0)
import rematch = re.match(r'[1-9]\d{5}','BIT 10081')if match:	match.group(0)match = re.match(r'[1-9]\d{5}','10081 BIT')if match:	match.group(0)

match可以返回空,调用group会出错

re.findall(pattern,string,flags=0)

搜索字符串,以列表类型返回全部能匹配的子串

import rels = re.findall(r'[1-9]\d{5}','BIT10081 TSU100084')ls
re.split(pattern,string,maxsplit=0,flags=0)

将一个字符串按照正则表达式匹配结果进行分割,返回列表类型

import rere.split(r'[1-9]\d{5}','BIT10081 TSU100084')re.split(r'[1-9]\d{5}','BIT10081 TSU100084',maxsplit=1)
re.finditer(pattern,string,flags=0)

搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象

import refor m in re.finditer(r'[1-9]\d{5}','BIT10081 TSU100084'):	if m:		print(m.group(0))
re.sub(pattern,repl,string,count=0,flags=0)

在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串

Re库的贪婪匹配和最小匹配

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

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

最小匹配

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

最小匹配 *** 作符

正则表达式概念

regular Expression
regex
re
正则表达式是用来简洁表达一组字符串的表达式


通用的字符串表达框架
简洁表达一组字符串的表达式
针对字符串表达“简洁”和“特征”思想的工具
判断某字符串的特征归属

正则表达式的语法


abc*:表示*前面的c可以出现0次或无限次,如ab,abc,abcc,…
abc+:表示+前面的c可以出现1次或无限次,如abc,abcc…



IP地址的正则表达式

淘宝商品比价定向爬虫
import requestsimport redef 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(plt):            price = eval(plt[i].split(':')[1])            Title = eval(Title[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_ulr+'&s='+str(44*i)            HTML = getHTMLText(url)            parsePage(infoList, HTML)        except:            continue    printGoodsList(infoList)main()
股票数据定向爬虫
import requestsfrom bs4 import BeautifulSoupimport tracebackimport redef getHTMLText(url):    try:        r = requests.get(url, timeout = 30)        r.raise_for_status()        r.enCoding = r.apparent_enCoding        return r.txt    except:        return ""def getStockList(lst, stockURL):    HTML = getHTMLText(stockURL)    soup = BeautifulSoup(HTML, 'HTML.parser')    a = find_all('a')    for i in a:        try:            href = i.attrs['href']            lst.append(re.findall(r"[s][hz]\d{6})",href)[0])        except:            continuedef 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')y        except:            traceback.print_exc()            continuedef main():    stock_List_url = 'http://quote.eastmoney.com/stockList.HTML'    stock_Info_url = 'http://gupiao.baIDu.com/stock/'    output_file = 'D://BaIDuStockInfo.txt'    sList = []    getStockList(sList, stock_List_url)    getStockInfo(sList, stock_info_url, output_file)main()
requests库和Scrapy爬虫比较

相同点:
都可以进行页面请求和爬取
可用性好
没有处理Js,提交表单

不同:
requests:页面级爬虫,功能库,并发性不足,页面下载,定制灵活,简单
Scrqpy:网站级爬虫,框架,并发性好,爬虫结构,深度定制困难,稍难

Scrapy爬虫的常用命令

Scrapy命令行格式

>scrapy<command>[options][args]

常用命令


命令行更容易自动化,适合脚本控制

本质上,Scrapy是给程序员用的,功能更重要

Scrapy爬虫框架介绍

爬虫框架是实现爬虫功能的一个软件结构和功能组件集合
爬虫框架是一个半成品,能帮助用户实现专业网络爬虫

Scrapy爬虫框架解析


Engine:控制抽有模块之间的数据流;根据条件触发事件(不需要用户修改)
Downloader:根据请求下载网页(不需要用户修改)
Scheduler:对所有爬虫请求进行调度管理(不需要用户修改)

Downloader MIDdleware:修改、丢弃、新增请求或响应
SpIDer:解析Downloader返回的响应;产生爬取项;产生额外的爬取请求
Item Pipelines:以流水线方式处理SpIDer产生的爬取项;由一组 *** 作顺序组成,类似流水线,每个 *** 作是一个Item Pipeline类型;清理、检验和查重爬取项中的HTML数据,将数据存储到数据库(需要用户编写)

SpIDer MIDdleware:修改、丢弃、新增请求或爬取项

Scrapy实例1

安装好Scrapy库后
打开命令提示符
输入d:
输入cd pycodes
输入scrapy startproject python123demo

scrapy.cfg:部署Scrapy爬虫的配置文件
python123demo:Scrapy框架的用户自定义Python代码
_init_.py:初始化脚本
items.py:Items代码模板(继承类)
mIDdlewares.py:MIDdlewares代码模板(继承类)
pipelines.py:Pipelines代码模块(继承类)
settings.py:Scrapy爬虫的配置文件

输入scrapy genspIDer demo python123.io

增加了一个新的文件demo.py,内容如下

# -*- Coding: utf-8 -*-import scrapyclass DemoSpIDer(scrapy.SpIDer):	name = "demo"	allowed_domains = ["python123.io"]	start_urls = ['http://python123.io/']		def parse(self, response):		pass

parse()用于处理响应,解析内容形成字典,发现新的URL爬取请求

修改demo.py

# -*- Coding: utf-8 -*-import scrapyclass 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('Save file %s.' %name)

输入scrapy crawl demo

Scrapy爬虫的基本使用

创建一个工程和SpIDer模板
编写SpIDer
编写Item Pipeline
优化配置策略

Requests类


Response类


Item类

Scrapy爬虫提取信息的方法
BeautifulSoup
lxml
re
XPath Selector
CSS Selector

yIEld关键字的使用

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

def gen(n):	for i in range(n):		yIEld i**2
股票数据Scrapy爬虫实例

建立工程和SpIDer模板
编写SpIDer
编写ITEM Pipelines

输入:
scrapy startproject BaIDuStocks
cd BaIDuStocks
scrapy genspIDer stocks baIDu.com

修改spIDers/stocks.py

# -*- Coding: utf-8 -*-import scrapyimport reclass StockSpIDer(scrapy.SpIDer):	name = "stocks"	start_urls = ['http://quote.eastmoney.com/stockList.HTML']		def parse(self, response):		for href in response.CSS('a::attrs(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		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(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.py文件

class BaIDustockPipeline(object):	def process_item(self, item, spIDer):		return item	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

ITEM_PIPElines = {	'BaIDuStocks.pipelines.BaIDustocksInfoPipeline':300,}

执行:scrapy crawl stocks

总结

以上是内存溢出为你收集整理的Python网络爬虫与信息提取全部内容,希望文章能够帮你解决Python网络爬虫与信息提取所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1186728.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存