您的位置:首页 > 编程语言 > Python开发

python爬虫学习

2018-03-07 18:08 309 查看

爬数据,爬数据

 这是在新的互联网时代必然的要求,搞定从爬虫到数据分析再到人工智能一整套体系已经似乎是每个程序员的必备知识了。于是乎,就先来学习下爬虫的应用

 我学习的是中国大学MOOC上北理嵩天教授的视频课程,博客仅为记录为日后参考。

一:requests中基本功能的了解

  1.用anconda安装requests:

conda install requests


 2.在jupyter notebook中导入requests包:

import requests


 3.了解requests的基本爬取形式即get的方法

'''
get方法以及其他post,push,put,delete,head等都和
http的get,post,push,delete,head相对应
'''
r = requests.get("https://www.baidu.com")
#而这些方法其实都是requests.request的封装而已,上句就相当于:
r = requests.request('get', "https://www.baidu.com")
#其中使用head方法也是返回response,只不过之能读取其html中headers的内容
x = requests.head("http://www.baidu.com")
print type(x)
print x.status_code
print x.headers


  4.了解response基本用法

#http请求的返回状态,200代表响应成功
print r.status_code
#从header中猜测响应内容的编码方式
#如果header中没有charset字段就默认编码为ISO-8859-1
print r.encoding
#从内容中分析响应内容的编码方式
print r.apparent_encoding
#打印r的所带头部
print r.headers
#用二进制编码形式显示内容
print r.content
#用文本型编码形式显示内容
print r.text


 5.网页编码形式可能会导致乱码,这就需要对编码进行修改,使用apparent方法可以更好的对编码进行修正

import requests
url = "http://www.baidu.com"
r = requests.get(url)
print r.apparent_encoding
r.encoding = 'utf-8'
print r.text


在完成了上述内容学习后,可以简单的写出一个爬取的框架

#爬取全部的框架
def getHTMLText(url):
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()#如果状态不是200就引发HTTPError异常“
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
#只爬取头部header的框架
def headHTTPHeaders(url):
try:
r = requests.head(url, timeout = 30)
r.raise_for_status()
return r.headers
except:
return "产生异常"


 6.在对页面进行爬取的时候,有时需要筛选你要的内容(搜索,这就需要api接口为基础),这时候就需要用到request中的params属性

kv = {"key1":"test", "key2":"test"}
#params是可以让一些参数加入到url可以筛选资源
y = requests.request("get", "http://acm.hdu.edu.cn/", params = kv)
#或者如下
y = requests.get("http://acm.hdu.edu.cn/", params = kv)
print y.url
print y.text


 在对页面进行爬取时,有时候需要提交一些信息,如用户登陆时提供username和password等,就需要data属性

#data是作为request的内容提交,这时候不放在url的链接里而是作为数据提交
r = requests.request("post", "http://acm.hdu.edu.cn/",data = kv)
print r.url
print r.text


 而除此之外还有许多其他的属性都可以使用如:json(用于js),headers,cookie, auth, files,timeout(以秒为单位),proxie,allow_redirects, stream, verify, cert等等。

 7.很多时候爬虫的滥用可能会导致网站服务器的宕机以及一些安全性的不确定,所以基本现在所有网站都有爬虫协议,规定了什么内容是可以爬,什么是禁止的。当然如果是类自然人的爬虫操作就相当于人类访问,所以这类爬虫的访问没有大碍也无需限制。

def getHTMLrobots(url):
try:
r = requests.get(url + "/robots.txt", timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "访问异常"
if __name__ == "__main__":
url = "http://acm.hdu.edu.cn"
print getHTMLrobots(url)


二:一些实例(都是老师的例子啦)

 1.爬取JD商品页面

  一个初步的练习,用来熟悉requests的基本操作

#request爬取JD商品信息
import requests
def getHTMLstatus(url):
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()
return r.status_code
except:
return "异常连接"
def headHTTPHeaders(url):
try:
r = requests.head(url, timeout = 30)
r.raise_for_status()
return r.headers
except:
return "产生异常"
def getHTMLText(url):
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()#如果状态不是200就引发HTTPError异常“
r.encoding = r.apparent_encoding
return r.text#[XXXX:XXX(这里输入数字代表从多少到多少输出)]
except:
return "产生异常"
if __name__ == "__main__":
url = "https://item.jd.com/2967929.html"
print getHTMLstatus(url)
print headHTTPHeaders(url)
print getHTMLText(url)


 2.爬取amazon的商品信息

  按照老师的说法可能会产生访问失败可是本人并没有访问失败,可能和amazon接口开放情况有关,但还是需要掌握有时网站会检测访问的header是否是爬虫,此时就需要改变header。

import requests
r = requests.get("https://www.amazon.cn/gp/product/B01M8L5z3Y")
print r.status_code
print r.headers
print r.encoding
print r.apparent_encoding
print r.text[1000:2000]
kv = {'user-agent':'Mozilla/5.0'}
url = "https://www.amazon.cn/gp/product/B01M8L5z3Y"
r = requests.get(url, headers = kv)
print r.status_code
print r.headers


 3.百度/360搜索关键词提交

  其实在搜索引擎的具体做中都是有搜索的接口的,我们要练习用最本源的方法去看待计算机网络,而且这里用到了params属性来搜索关键字

'''
百度/360搜索关键词提交
百度的关键词接口是http://www.baidu.com/s?wd = keyword
360是:http://www.so.com/s?q = keyword
'''
import requests
kv = {'wd':'python'}
r = requests.get("http://www.baidu.com/s", params = kv)
print r.status_code
print r.url
print len(r.text)

import requests
def grabble_360_q(keword):
try:
kv = {'q':keyword}
r = requests.get("http://www.so.com/s", params = kv)
print r.url
r.raise_for_status()
return len(r.text)
except:
return "连接失败"
if __name__ == "__main__":
keyword = 'python'
print grabble_360_q(keyword)


 4.网络图片的爬取

  在知道了图片的url以后,我们就可以像爬取网页一样爬取图片,用二进制的方式存储,但是有时候网站呢会限制你当爬取,就要利用稍微更强力的方法爬取比如urllib2。

#网络图片的爬取和存取
import requests
path = "F:/work_python/reptile/abc.jpg"
url = "http://img0.dili360.com/rw9/ga/M02/4A/4E/wKgBy1qXx_iAMZpGAAFp4lJakJg107.jpg"
r = requests.get(url)
print r.status_code
with open(path, 'wb') as f:
f.write(r.content)
f.close()

#图片爬取全代码
import requests
import os
def get_image_url(url, root):
try:
path = root + url.split('/')[-1]
print path
print root
if not os.path.exists(root):
os.mkdir(root)
if not os.path.exists(path):
r = requests.get(url)
print r.status_code
with open(path, 'wb') as f:
f.write(r.content)
f.close()
print "文件保存成功"
else:
print "文件已存在"
except:
print "爬取失败"
if __name__ == "__main__":
url = "http://img0.dili360.com/rw9/ga/M02/4A/4E/wKgBy1qXx_iAMZpGAAFp4lJakJg107.jpg"
root = "F:/work_python/reptile/"#F://work_python//reptile//也行
get_image_url(url, root)


#网络图片的爬取和存取(遭遇了反爬虫机制,网上学习了用urllib2的方法)
import requests
path = "F:/work_python/reptile/abc.jpg"
url = "https://t10.baidu.com/it/u=2186154957,3923158064&fm=173&s=39843C7A8875B29A5D540CDD0100C0A2&w=640&h=441&img.JPEG"
r = requests.get(url)
print r.status_code
print r.headers
kv = {'user_agent':'Mozilla/5.0'}
r = requests.get(url, headers = kv)
print r.status_code
import urllib2
r = urllib2.Request(url)
r.add_header("User-Agent","Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36")
r.add_header("GET",url)
r.add_header("Host","t10.baidu.com")
r.add_header("Referer","https://t10.baidu.com/it/")
with open(path, 'wb') as f:
f.write(urllib2.urlopen(r).read())
html=urllib2.urlopen(r)
#print html.read()
f.close()


 5.网络ip地址的追寻

  其实老师还是用的是第三方查询的方法,利用api接口接入查询

#ip地址归属查询(ip138.com)
import requests
url = "http://m.ip138.com/ip.asp?ip="
r = requests.get(url + '202.204.8.112')
print r.status_code
key = '202.204.8.112'
kv = {'ip':key}
url = "http://m.ip138.com/ip.asp"
r = requests.get(url, params = kv)
print r.request.url
print r.url
print len(r.text)
#print r.text[-500]#代表最后500个字节


三:BeautifulSoup库的基础

 BeautifulSoup是一个强大的标签解析库,它能够针对html的文本内容做解析查找等内容,其包含的搜索函数也非常强大,可以满足很多信息提取的功能。

1.安装BeautifulSoup库

 打开anconda输入以下代码即可安装最新你版本的BeautifulSoup:

conda install BeautifulSoup4


 在具体使用时导入的代码如下

from bs4 import BeautifulSoup


2.做soup

 在使用BeautifulSoup之前我们需要html的text文件以及对此文件的解析。html我们可以使用requests库的方法获得,代码如下,可以直接用最简单的方法获取:

import requests
r = requests.get("ttps://python123.io/ws/demo.html")
demo = r.text


也可以将文件存下来,在以后可以用本地的方式来获取

import requests
import os
def get_html(url, root):
try:
path = root + url.split('/')[-1]
print path
print root
if not os.path.exists(root):
os.mkdir(root)
if not os.path.exists(path):
try:
r = requests.get(url)
r.raise_for_status()
print r.status_code
with open(path, 'wb') as f:
f.write(r.content)
f.close()
print "文件保存成功"
except:
print "连接失败"
else:
print "文件已存在"
except:
print "爬取失败"
root = "F:/work_python/reptile/"
get_html("https://python123.io/ws/demo.html",root)
with open("F:/work_python/reptile/demo.html", 'r') as f:
demo = f.read()
f.close


 在完成了对text文件的获取后,我们就可以开始煮汤了用如下语句即可

from bs4 import BeautifulSoup
soup = BeautifulSoup(demo, 'html.parser')


 这里的‘html.parser’是BeautifulSoup库中支持的解析方式,针对不同格式,可以有不同的解析方式

'''
bs4的html解析器BeautifulSoup(mk,'html.parser')
lxml的html解析器BeautifulSoup(mk, 'lxml') //install lxml
lxml的xml解析器BeautifulSoup(mk, 'xml') //install lxml
html5lib的解析器BeautifulSoup(mk, 'html5lib') //install html5lib
'''


3.bs4库的基本元素

 在做完汤后,我们就要开始对其进行一些操作了,其中soup可以完成的基本操作有:

 1. 标签tag

 2. 标签名name

 3. 标签属性attrs

 4. 标签内容string

 5. 标签注释comment

 而soup本身就是一个tag,我们可以用name去寻找特定标签,用attrs去寻找标签中的属性,用string去寻找标签中的内容etc

tag = soup.a
print tag.name
print tag.attrs#读取出来是一个字典
print tag.attrs['href']
print tag.string
print tag.comment


4.遍历的方法

 在BeautifulSoup中有三种遍历的方法分别是:

 下行遍历

 上行遍历

 平行遍历

(1)下行遍历

 下行遍历有如下三种方法:

 .contents的对所有子节点的输出

 .children的对所有子节点遍历

 .descendants对所有子孙结点遍历

#contents是所有的儿子结点
print soup.head.contents
#contents不仅包括了标签结点,字符串也是子节点
print soup.body.contents[0]
print soup.body.contents[1]
print type(soup.body.children)
#可以用children和descendants分别对子节点和子孙结点进行遍历
for child in soup.b
c850
ody.children:
print child
for child in soup.body.descendants:
print child


(2)上行遍历

 上行遍历有如下两种方法:

 .parent返回结点的父亲标签

 .parents结点先辈的迭代类型

print soup.title.parent
#html是最高级的标签其父亲就是其本身
print soup.html.parent
#soup的父亲为空
print soup.parent
#迭代访问需要注意soup的特殊情况
for parent in soup.a.parents:
if parent is None:
print parent#即空的没有name的信息
else:
print parent.name


(3)平行遍历

 平行遍历有如下四种方法:

 1. .next_sibling:返回按照html文本顺序的下一个平行结点标签

 2. .previous_sibling:返回。。。上一个平行结点标签

 3. .next_siblings: 1的迭代器

 4. .previous_sibling: 2的迭代器

注意平行遍历发生在同一个父节点下的个节点间

#这里可以发现navigablestring也是结点
print soup.a.next_sibling
print soup.a.next_sibling.next_sibling
print soup.a.previous_sibling
#如果到头了就会返回空
print soup.a.previous_sibling.previous_sibling
print soup.a.parent
for sibling in soup.a.next_siblings:
print sibling
for sibling in soup.a.previous_siblings:
print sibling


5.更好的显示html代码

.prettify()


四:三种信息的标记形式

 信息的内容非常重要,同时,信息的组织方式可以让我们更好的提取信息,这就需要对信息的标记形式进行了解

1:xml:extensible markup language

 与html类似,用< > … < /> 或< / >的方式来标记内容,其中有name和信息

如 < img src = ” ” size = ” ” >< /img >

img就是name,src等就是attribute

,也可以有注释 < !– – >

2.json:javascript object notation

 有类型的键值对表达的类型key:value

“key”:”value”都是要通过增加双引号来表达是字符串而数字不用双引号,这说明是有数据类型的

“key”:[“value1”,”value2”]一个key可以对应两个value

“key”:{“newkey”:”value1”, “oldname”:”value2”}key是可以嵌套使用的

3.yaml:yaml ain’t markup language

 无类型的键值对key:value

key:value不用双引号

用缩进来体现关系

用-来体现并列关系

用|变现整块数据

用#来注释

key : value

key : #comment

-value

-value

key:

  key: value

信息提取的一般方法

完整解析信息的标记形式,需要标记解析器如bs4,可能比较慢

无视标记形式,直接搜索对信息的文本查找函数,但是缺少准确性

结合1,2需要标记解析器和文本查找函数:

如提取html所有url链接:

(1)搜索到所有< a >标签

(2)解析< a >标签格式,提取href后的链接内容

from bs4 import BeautifulSoup
with open("F:/work_python/reptile/demo.html", 'r') as f:
demo = f.read()
f.close()
soup = BeautifulSoup(demo, 'html.parser')
for link in soup.find_all('a'):
print (link.get('href'))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: