http协议采用URL作为定位网络资源的标识
每个URL格式:http://host[:port][path]
host:一个合法的Internet主机域名或IP地址
port:端口号,缺省为80
path:请示资源的路径
URL通过http协议存取资源的Internet路径,一个URL对应一个资源
http协议方法:
若URL有一组数据UserInfo,包含UserID、Username等20个字段,要修改Username,其他不变,PATCH仅向URL提交Username的局部更新请示,PUT必须要提交所有字段,未提交的字段被删除。所以PATCH方法可以节省带宽
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()方法会覆盖原有的数据
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<command>[options][args]
常用命令
命令行更容易自动化,适合脚本控制
本质上,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语句的函数是一个生成器
生成器每次产生一个值,函数被冻结,被唤醒后再产生一个值
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网络爬虫与信息提取所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)