爬虫
爬虫的原理
先利用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()