爬虫

爬虫的原理

先利用requests的get或者post从网页上获取请求,返回一个response对象,通过contents或text读取response文本内容形成html文档,然后利用beautifulsoup对html文档进行解析。

Reuqests库

requests支持两种网页获取方式,一种是requests.get(),一种是requests.post(),重要的是表头和其他参数,尤其表单数据。

获取网页

r = requests.get('https://api.github.com/events')
r = requests.post('http://httpbin.org/post', data = {'key':'value'})

传递URL参数

像搜索引擎中搜索关键字可以通过传递URL参数关键字实现,以键值字符串来提供

payload = {'key1':'value1','key2':'value2'}
r = requests.get("http://httpbin.org/get",params = payload)
print(r.url)

http://httpbin.org/get?key2=value2&key1=value1

响应内容

获取网页后会得到一个response的对象,可以获取response对象的内容,大多数unicode字符集都能被无缝解码,如果出现中文乱码,则可以通过response.encoding查看文档编码,编码方式可以改变

1 import requests
2 r = requests.get('https://api.github.com/events')
3 r.text 
4 print(r.encoding)
5 'utf-8' 
6 r.encoding = 'ISO-8859-1' #更改文档编码方式

除了获取response.text(unicode型数据)还可以获取response.content 二进制数据

定制表头

定制表头是为了模拟浏览器进行操作可以防止反爬虫,表头传入的是字典

1 url = 'https://api.github.com/some/endpoint'
2 headers = {'user-agent': 'my-app/0.0.1'}
3 r = requests.get(url, headers=headers)

定制表单

对于动态网址经常会遇到翻页或URL不变的情况,通常影响因素就是表单,form_data

form_data={'D1':'008'}
page=requests.post(url,headers=headers,data=form_data)

Beautifulsoup库

主要是对html或者xml文档进行解析,支持两种文档解析方式,一种是利用find_all,一种是CSS解析,最关键的是里面属性的应用,包括tag,attrs,string,text,子节点和父节点的应用

soup = beautifulsoup(html)

beautifulsoup对象

利用beautifulsoup()接口解析文档可以生成一个beautifulsoup对象,利用prettify()可以格式化输出

四大对象种类

Tag

Tag 是html文档中的标签,可以直接使用soup.a获取第一个a标签。Tag有两个属性,一个是name,一个是attrs,其中attrs可以帮助我们定位tag,属于经常会用到的对象

print soup.a
#<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>

NavigableString 

naviablestring可以获取tag中的内部文字,soup.a.string,同时text函数也可以获取,二者的主要区别是string可以获取注释里的内部文字,但是text则不行

1 test = '<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>'
2 test1 = bs(test)
3 test1.a.string #' Elsie '
4 test1.a.text # ' '

Comment

comment是一种特殊的NavigableString对象,输出内容不包括注释符号,但是它的内部文字实际上是注释而不是直接的文字,注意navigablestring,text的区别

遍历文档树

解析完html文档生成文档树后,要对文档树进行遍历获取所需要的内容,常用的属性有Tag,Attrs,children,parents,contents,next_sibling,previous_sibling,next_element

所搜文档树

find_all(name,attrs,recursive,text,**kwargs),其中name通常指tag,可以传入列表['a','p']指满足任何一个tag即可,attrs是tag的属性通常和正则表达式或True结合使用,除此之外还可以传方法tag.has_attr(' ')表示tag是否有某个属性

def has_class_but_no_id(tag):
    return tag.has_attr('class') and not tag.has_attr('id')

soup.find_all(has_class_but_no_id)

**keyword参数:如果一个指定名字的参数不是搜索内置的参数名,搜索时会把该参数当作指定名字tag的属性来搜索

soup.find_all(id='link2')
# [<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]
soup.find_all(href=re.compile("elsie"))
# [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]

 网页类型

网页分为静态网页和动态网页,动态网页(ajax异步加载)要比静态网页复杂,主要提现在需要前后端交互,前端需要发送JS数据到服务器,服务器返回相应内容后由前端进行加载渲染成相应的页面,其地址栏中URL并不包含实际的html文档,可以通过XHR判断一个网页是不是ajax异步加载。通过network中的preview查看返回的相应URL。Ajax网页URL后通常会有"?"表示需要查询的内容,利用urlencode可以将网页和查询内容通过键值对的形式结合在一起。还有一种既不是AJAX异步加载,也不是静态网页,因为没有XHR,翻页或选择时URL不变,这时主要是通过表单数据控制,可以通过html中form查看。

URL 中文编码

URL只允许一部分ASCII字符(数字字母和部分符号),其他的字符(汉字)是不符合URL标准的,所以要对URL中特殊字符尤其汉字进行编码。在Python3.x中可以利用urllib.parse.quote(text,safe=string.printable)进行编码,safe表示哪些字符不会被编码,string.printable显示的一些字符。

1 url = "http://www.ischoolbar.com/index.php/School/schools.html?province=1&provincename=北京"
2 
3 url_new = parse.quote(url,safe=string.printable)
4 
5 http://www.ischoolbar.com/index.php/School/schools.html?province=1&provincename=%E5%8C%97%E4%BA%AC

 Session和Cookie

有的时候在不同的页面会出现request url相同的情况,通常情况下是通过cookie控制的,不同的Session会有不同的cookie,根据不同的cookie解析相同URL,返回的内容也会不同

url_t = "http://www.ischoolbar.com/index.php/School/selectSchool.html?id=920&name=%E6%B5%99%E6%B1%9F%E5%A4%A7%E5%AD%A6"
s = requests.Session()
r = s.get(url_t)
r_1 = s.get("http://www.ischoolbar.com/index.php/Goods/getGoods.html?pn=1")
r_1.json()
原文地址:https://www.cnblogs.com/mango-lee/p/9829171.html