python爬取下厨房网站首页图片request+bs4
原创
©著作权归作者所有:来自51CTO博客作者OceanSec的原创作品,请联系作者获取转载授权,否则将追究法律责任
注:东西太多,总结的不算太全,系统学习的话,出门右拐B站等你
爬虫:
- 一段自动抓取互联网信息的程序,从互联网上抓取对于我们有价值的信息。
网页爬取
工具
-
CURL
:cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。 - 基本使用方法:
curl url (获取网站全部信息)
curl -i url(获取该网址的文本信息以及协议头部信息)
curl -x proxy url(使用代理获取网页文本信息)
curl -X POST --header"Content-Type:application/json" --data ‘{}’ url (使用post模拟json格式请求接口)
curl -I url(仅返回请求头部信息)
header:
POST -d或-F #携带post参数
HEAD -I #携带http文件头
PUT -T #
- wget
wget虽然功能强大,但是使用起来还是比较简单的,基本的语法是:wget [参数列表] URL。
wget url #下载整个http
wget -r url #递归下载
python库
- urllib
from urllib import request
urllib的request模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应
from urllib import request
with request.urlopen('https://api.douban.com/v2/book/2129650') as f:
data = f.read()
print('Status:', f.status, f.reason)
for k, v in f.getheaders():
print('%s: %s' % (k, v))
print('Data:', data.decode('utf-8'))
可以看到HTTP响应的头和JSON数据:
Status: 200 OK
Server: nginx
Date: Tue, 26 May 2015 10:02:27 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 2049
Connection: close
Expires: Sun, 1 Jan 2006 01:00:00 GMT
Pragma: no-cache
Cache-Control: must-revalidate, no-cache, private
X-DAE-Node: pidl1
Data: {"rating":{"max":10,"numRaters":16,"average":"7.4","min":0},"subtitle":"","author":["廖雪峰编著"],"pubdate":"2007-6",...}
urlparse
python3中urlparse模块和urllib模块合并,urlparse()在urllib.parse中进行调用。
urlparse()把url拆分为6个部分,scheme(协议),netloc(域名),path(路径),params(可选参数),query(连接键值对),fragment(特殊锚),并且以元组形式返回。
from urllib.parse import urlparse
url = 'https://github.com/search?q=krislp'
parse = urlparse(url)
print(parse)
输出结果
ParseResult(scheme='https', netloc='github.com', path='/search', params='', query='q=krislp', fragment='')
- requests
它是一个Python第三方库,处理URL资源特别方便。
使用requests
>>> import requests
>>> r = requests.get('https://www.douban.com/') # 豆瓣首页
>>> r.status_code
200
>>> r.text
r.text
'<!DOCTYPE HTML>\n<html>\n<head>\n<meta name="description" content="提供图书、电影、音乐唱片的推荐、评论和...'
网页解析
- bs4
根据标签名进行获取节点
只能找到第一个符合要求的节点
获取文本内容和属性
属性:
soup.a.attrs 返回一字典,里面是所有属性和值
soup.a[‘href’] 获取href属性
文本:
find:
soup.find(‘a’)
soup.find(‘a’, class_=‘xxx’)
soup.find(‘a’, title=‘xxx’)
soup.find(‘a’, id=‘xxx’)
soup.find(‘a’, id=re.compile(r’xxx’))
find只能找到符合要求的第一个标签,他返回的是一个对象
find_all
返回一个列表,列表里面是所有的符合要求的对象
soup.find_all(‘a’)
soup.find_all(‘a’, class_=‘wang’)
soup.find_all(‘a’, id=re.compile(r’xxx’))
soup.find_all(‘a’, limit=2) 提取出前两个符合要求的a
from bs4 import BeautifulSoup
# 生成soup对象
soup = BeautifulSoup(open('soup.html', encoding='utf8'), 'lxml')
print(type(soup))
print(soup.a.attrs)
print(soup.a.attrs['href'])
print(soup.a['href'])
print(soup.a.string)
print(soup.a.text)
print(soup.a.get_text())
print(soup.div.string)
print(soup.div.text)
print(soup.div.get_text())
ret = soup.find('a')
ret = soup.find('a', title='清明')
ret = soup.find('a', class_='dumu')
print(ret)
import re
ret = soup.find('a', id='xiaoge')
ret = soup.find('a', id=re.compile(r'^x'))
print(ret.string)
ret = soup.find_all('a')
print(ret[1].string)
ret = soup.find_all('a', class_='wang')
print(ret)
ret = soup.find_all('a', id=re.compile(r'^x'))
print(ret)
ret = soup.select('a')
ret = soup.select('#muxiong')
print(ret[0]['title'])
ret = soup.select('.wang')
print(ret)
ret = soup.select('div > a')
print(ret)
ret = soup.select('a[title=东坡肉]')
print(ret)
odiv = soup.select('.tang')[0]
ret = odiv.select('a')
print(ret)
文件操作
读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
- 读文件
要以读文件的模式打开一个文件对象,使用Python内置的open()函数,传入文件名和标示符:
f = open('/Users/michael/test.txt', 'r')
如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示:
>>> f.read()
'Hello, world!'
最后一步是调用close()方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的:
- 写文件
你可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险:
>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()
requests.get(url)默认是下载在内存中的,下载完成才存到硬盘上,可以用Response.iter_content 来边下载边存硬盘
import os
from urllib.parse import urlparse
import requests
from bs4 import BeautifulSoup
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36 Edg/83.0.478.37'}
url='http://www.xiachufang.com/'
r=requests.get(url,headers=headers)
soup=BeautifulSoup(r.text)
# print(r.text)
img_list=[]
for img in soup.select('img'):
# print(img,end='\n\n')
if img.has_attr('data-src'):
# print(img.attrs['data-src'],end='\n\n')
img_list.append(img.attrs['data-src'])
else:
img_list.append(img.attrs['src'])
# print(img.attrs['src'])
img_dir=os.path.join(os.curdir,'images')
if not os.path.isdir(img_dir):
os.mkdir(img_dir)
for img in img_list:
o=urlparse(img)
filename=o.path[1:].split('@')[0]
filepath=os.path.join(img_dir,filename)
print(filename)
img_url='%s://%s/%s'%(o.scheme,o.netloc,filename)
resp=requests.get(img_url,headers=headers)
print(img_url)
with open(filepath,'wb') as f:
for chunk in resp.iter_content(1024):
f.write(chunk)