python我从今年过年开始自学,断断续续的,最近参加了一个爬虫训练营,我发现爬虫对开始学习python是非常合适的,只不过首先得具备一些HTML的知识储备,毕竟爬虫是需要解析网页的。而且爬虫实现后的成就感是非常巨大的。所以,根据上周学习的一些知识,做一个小的总结。
首先需要安装requests库和beautifulsoup库,这两个库是有函数可以对网页进行一个解析操作的。比如request中的get()。beautifulsoup中的Beautifulsoup()的使用。
安装过程
首先最简单的安装就是利用cmd通过pip指令安装
pip install requests
pip install beautifulsoup4 //这里需要注意一下,后面必须有个4。
如果安装不上,那就从网上先下载好需要的安装文件,在进入该文件的目录下,进行安装。
request的使用
request的请求方式有多种,因为是一个第三方库,有多种使用方法,可以在网上寻找一些使用文档参考
requests.get('http://www.xxxxxxxx.com')
requests.post('http://www.xxxxxxxx.com')
requests.delete('http://www.xxxxxxxx.com')
requests.put('http://www.xxxxxxxx.com')
requests.head('http://www.xxxxxxxx.com')
列举一些常用的。
get:请求指定的页面信息,并返回一个主体。使用get方式时,请求数据直接放在url中。
post:请求主要是发送一些较长的数据,数据比较安全 。使用post方式时,数据放在data或者body中,不能放在url中,放在url中将被忽略。
delete:请求服务器删除Request-URI所标识的资源。
put:向指定资源位置上传其最新内容 。
head: 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
request的实例
首先我们要爬取的是猫眼网站的top100榜单。网址为http://maoyan.com/board/4。
这是第一页的情况,此时我们点击一个下一页,就能发现网址发现了变化。
能明显看到网址的变化是http://maoyan.com/board/4?offset={}。
不断去往下翻页,我们就能看到offset=后面这个数在不断的变化,第一页是0,到最后一页是90。
说明offset是偏移量,等于号后面的是偏移量的值
知道了这个url的规律之后,就可以来进行获取网址了。
通过get去获取一个网页信息
def get_url(url):
try:
wb_data=requests.get(url)
wb_data.raise_for_status
wb_data.encoding=wb_data.apparent_encoding
return wb_data.text
except:
return "代码段异常"
上面是单个网页去抓取。我们能发现,此时所有的html页面信息都被反馈出来了。
我们利用谷歌浏览器打开该网站,右键点击检查,我们能看到各个标签内的字符串在其中,这个时候我们就需要正则表达式将其提取出来。
def parse_one_page(html):
pattern=re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)
items=re.findall(pattern,html)
for item in items:
yield{
'index':item[0],
'img':item[1],
'名称':item[2],
'主演':item[3].strip()[3:],
'上映时间':item[4].strip()[5:]
}
关于正则表达式不在这里详细说了,以后我会专门写一篇总结。
yield的用法:如果一个函数包含yield
关键字,这个函数就会变为一个生成器。
生成器并不会一次返回所有结果,而是每次遇到yield
关键字后返回相应结果,并保留函数当前的运行状态,等待下一次的调用。所以在我们去请求网页的过程中,每寻找一次,找到相对应的标签,就将其内容爬取下来。
接下来需要对offset这个偏移量找到方法将他添加到我们的url中,并且可以循环的使用。
def main(offset):
url='http://maoyan.com/board/4?offset={0}'.format(offset)
html=get_url(url)
for item in get_url(html):
print(item)
format函数就不需要多说了,就是往其中添加字符串。这里利用一个for循环使用,这样可以循环将网页都在函数get_url中请求一次。
最后将它输出出来
for i in range(10):
main(offset=i*10)
time.sleep(2)
在控制台观察,就会发现我们需要的网页信息被一个一个的提取出来了。
这里使用了一个time.sleep(2),它的作用是让请求有一定的间隔,我们都知道各个网站具有反爬虫机制,如果访问太频繁,则会被禁止访问。让2s访问一次,则可以避免这种机制。
这就是一个简单的爬取过程。接下来是更具体的一种。利用了beautifulsoup来使用
BeautifulSoup的用法
‘美味汤’,是用Python写的一个HTML/XML的解析器,它可以很好的处理不规范标记并生成剖析树(parse tree)。 它提供简单又常用的导航(navigating),搜索以及修改剖析树的操作。它可以大大节省你的编程时间。
//引用该库的方法不是直接import就可以,而是通过from
form bs4 import beautifulsoup
soup=BeautifulSoup(wb_data.text,'lxml')
print(soup.find_all('a'))
print(soup.get_text())
//以上是举例它的写法
soup 就是BeautifulSoup处理格式化后的字符串,soup.title 得到的是title标签,soup.p 得到的是文档中的第一个p标签,要想得到所有标签,得用find_all
函数。find_all 函数返回的是一个序列,可以对它进行循环,依次得到想到的东西.
get_text() 是返回文本,这个对每一个BeautifulSoup处理后的对象得到的标签都是生效的。
我们在上面看到一个‘lxml’这个东西,这是解析库。在这里说明一下
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
python标准库 | BeautifulSoup(markup,‘parser’) | python内置;执行速度适中;文档容错能力强 | 低版本pyton容错能力差 |
lxml HTML解析器 | BeautifulSoup(markup,‘lxml’) | 速度快;容错能力强 | 需要安装lxml |
lxml XML解析器 | BeautifulSoup(markup,‘xml’) | 速度快;唯一支持XML | 需要安装lxml |
Html5lib | BeautifulSoup(markup,‘html5lib’) | 容错性最好 | 速度慢;需要安装html5lib |
在我们知道解析器之后,我们还要做的就是通过什么去选择标签。这里一般有四种常用选择器
选择器 | 作用 | 使用方法 |
---|---|---|
节点选择器 | 通过节点名称嵌套选取信息 | soup.div.next_sibling.ul.li.p |
方法选择器 | find_all()和find()函数 | soup.find(name=‘p’,class=’ ') |
css选择器 | Select方法 | body>div.content>ul>li:nth-child(1)>p |
Xpath | 用于在xml文档中搜索元素的路径语言 | /html/body/div[2]/ul/li[1]/p |
当我们基本了解之后就可以使用了。
在下面的使用中,就利用select方法
我们能看到黄色的地方就是我们需要的title标签所指向的地方。
右击这个标签,点击copy---->copy selector就是利用css选择器,这之后复制出来的标签走向最后复制到select()方法中。
def parse_one_page(html):
soup=BeautifulSoup(''.join(html),'lxml')
#在这里我们是得到了R.txt的文本,但是我们不能输出,所以我们得利用print来输出
titles=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-info > p.name > a')
pics=soup.select('#app > div > div > div.main > dl > dd > a > img.board-img')
actors=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-info > p.star')
days=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-info > p.releasetime')
scores1=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-number.score-num > p > i.integer')
scores2=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-number.score-num > p > i.fraction')
for title,pic,actor,day,scores,scoress in zip(titles,pics,actors,days,scores1,scores2):
info={
'title':title.get_text(),
'pic':pic.get('alt'),
'actor':actor.get_text(),
'day':day.get_text(),
'scores':scores.get_text()+scoress.get_text(),
}
write_to_file(info)
print(info)
在上面有一个自己定义的wirte_to_file()函数。爬取完数据后,一直放在控制台显示只能证明我们爬取成功了。所以定义函数将我们所请求到的数据放入一个文件中,可以供我们需要的时候看看。
def write_to_file(content):
with open('maoyan.text','a',encoding='utf-8') as f:
f.write(json.dumps(content,ensure_ascii=False)+'\n')
with open()这个函数的使用时,有四种文本可以保存,分别是text,json,csv,excel。后两种还可以利用pandas来处理统计。
完整代码
import json
import requests
import time
from bs4 import BeautifulSoup
def get_one_page(url):
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.104 Safari/537.36 Core/1.53.2263.400 QQBrowser/9.5.10429.400'}
response=requests.get(url,headers=headers)
if response.status_code==200:
return response.text
else:
return None
data=[]
def parse_one_page(html):
soup=BeautifulSoup(''.join(html),'lxml')
#在这里我们是得到了R.txt的文本,但是我们不能输出,所以我们得利用print来输出
titles=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-info > p.name > a')
pics=soup.select('#app > div > div > div.main > dl > dd > a > img.board-img')
actors=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-info > p.star')
days=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-info > p.releasetime')
scores1=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-number.score-num > p > i.integer')
scores2=soup.select('#app > div > div > div.main > dl > dd > div > div > div.movie-item-number.score-num > p > i.fraction')
for title,pic,actor,day,scores,scoress in zip(titles,pics,actors,days,scores1,scores2):
info={
'title':title.get_text(),
'pic':pic.get('alt'),
'actor':actor.get_text(),
'day':day.get_text(),
'scores':scores.get_text()+scoress.get_text(),
}
write_to_file(info)
print(info)
def write_to_file(content):
with open('maoyan.excel','a',encoding='utf-8') as f:
f.write(json.dumps(content,ensure_ascii=False)+'\n')
def main(offset):
url='https://maoyan.com/board/4?offset='+str(offset)
html=get_one_page(url)
parse_one_page(html)
for i in range(10):
main(offset=i*10)
time.sleep(1)
以上就是我们的爬取过程,并不算复杂,而且是比较容易爬取的!可以让你瞬间有成就感的那种!
爬取出来的是放在字典内的,一条一条在文本文件中,观看是非常醒目的。动手试试吧!