python-对猫眼网的top100的爬取

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。

111

这是第一页的情况,此时我们点击一个下一页,就能发现网址发现了变化。

222

能明显看到网址的变化是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方法

333

我们能看到黄色的地方就是我们需要的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)

以上就是我们的爬取过程,并不算复杂,而且是比较容易爬取的!可以让你瞬间有成就感的那种!

爬取出来的是放在字典内的,一条一条在文本文件中,观看是非常醒目的。动手试试吧!

猜你喜欢

转载自blog.csdn.net/skrskr66/article/details/84710079