实战(二)轻松使用requests库和beautifulso

前言

实战(一)之使用自带urllib和re正则表达式获取电影详情页链接

其实大多情况下,python自带的urllib和re正则表达式已经可以满足我们的日常需求了,但是,聪明的世人怎么会满足于此呢,只有更好就没有最好。所以,就诞生了requests和beautifulsoup这两个作为爬虫的黄金组合。而python的魅力就在于此,你可以找到很多好用易上手到让你心头一颤的第三方库。

一、安装&简单使用入门。

1、安装

使用Pip可以很方便的安装:

pip install requests

pip install beautifulsoup4

2、requests 入门。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
复制代码     import requests

## get请求
r = requests.get('https://github.com/timeline.json')
r.json() ##如果是JSON 响应内容,使用r.json()会自动将json结果转换成dict
r.content() ##二进制相应内容

headers = {'user-agent': 'my-app/0.0.1'} #定制请求头
r = requests.get('https://github.com/timeline.json', headers=headers)

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

## post请求
payload = {'key1': 'value1', 'key2': 'value2'} ## post数据
r = requests.post("http://httpbin.org/post", data=payload)

## 上传文件
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)

更多详细的请查看官方的中文文档,详细易懂权威。

http://docs.python-requests.org/zh\_CN/latest/user/quickstart.html

3、beautifulsoup入门。

beautifulsoup可以快速的去定位HTML文档,HTML是用来描述网页的一种超文本标记语言,不是一种编程语言。
如果你没有HTML基础,可以去花一天的时间了解下。
菜鸟教程–HTML

http://www.runoob.com/html/html-tutorial.html

注意的点
  • 现在假设知道了HTML是个什么东西,你会发现HTML就是由一层又一层的tag组成,每个tag节点有自己的class属性或者其他属性、自己的父tag、子tag以及兄弟tag,而beautifulsoup的作用就是通过这种蛛丝马迹,轻易的把你要的凶手。。哦不目标节点揪出来,免去了写正则表达式的繁琐噩梦。
  • beautifulsoup对HTML的解释是依赖第三方解释库的,常用的有html.parser、lxml、支持xml解释的lxml-xml、html5Lib,各有优缺点,根据我的经验,有时候使用beautifulsoup返回的待处理文本,会缺少一些tag节点,但是你又确定这不是动态加载的话,其实这是因为解释器无法解释,直接跳过导致的,这时候,可以更换解释器尝试一下。
常用的方法

我这里只用下find和find_all作为实例,详细的用法请去权威易懂的官方文档。 毕竟做搬运工是件很累且无意义的事情。

http://beautifulsoup.readthedocs.io/zh\_CN/latest/

1
2
3
4
5
6
7
复制代码from bs4 import BeautifulSoup

##配合requests
r = requests.get('http://www.douban.com')
##一锅待处理的soup汤
soup = BeautifulSoup(r.content,'lxml') #使用lxml解释库
print(soup)

我们会得到如下的soup体,然后定位到红色框的a块。

image.png

通过属性定位查找该节点 (find)

1
2
3
4
复制代码    a = soup.find('a',attrs={'class':'lnk-book'})
print(a)
print('链接: '+a['href'])
print('文字: '+a.text)

image.png

返回包含所有该节点的列表(find_all)

1
2
复制代码a_s = soup.find_all('a')
print (a_s)

image.png

提示:有时候需要先将目标范围逐层缩小,这样容易获取目标节点。

二、爬取豆瓣图书top250

分析页面。

1、 我们点击底部的页码,会发现页数是25的倍数,从0开始,这样我们就可以构造对应页的url了。

image.png

2、我们定位到每页,查找书本的信息,获取对应的url,下图为每页爬取到的书本详情页url。

image.png

image.png

3、在图书的详情页,我们定位到如下元素。获取该书的书名,评分和评分人数。

image.png

image.png

代码编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
复制代码# -*- coding:utf-8 -*-

#author:waiwen
#email:iwaiwen@163.com
#time: 2017/12/3 12:27

from bs4 import BeautifulSoup
import requests
import random


#uer_agent库,随机选取,防止被禁
USER_AGENT_LIST = [
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
"Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
"Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
"Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]


#请求网页的代码整合
def get_response(url):
#random.choice从一个集合中随机选出请求头
headers = {'user-agent':random.choice(USER_AGENT_LIST)}

resp = requests.get(url,headers=headers)
resp.raise_for_status()
soup = BeautifulSoup(resp.content, 'lxml')
return soup

#找到每本书的链接
def get_book_url(page):
if page>10:
return []
num=(page-1)*25
url ='https://book.douban.com/top250?start=%s'%str(num)
soup = get_response(url)
book_div = soup.find('div', attrs={'class': 'indent'})
books = book_div.find_all('tr', attrs={'class': 'item'})
urls = [ book.td.a['href'] for book in books ]
print('获取第%s页'%page,urls)
return urls

#获得每本书的信息
def get_book_info(book_url):
soup = get_response(book_url)

div_info = soup.find('div',attrs={'id':'info'})

book_author = div_info.a.text.split(' ')[-1] #将空格去除
book = soup.find('div',attrs={'class':'rating_wrap clearbox'})
book_name= soup.find('span',attrs={'property':'v:itemreviewed'}).text

book_grade = book.find('strong',attrs={'class':'ll rating_num '}).text
book_man = book.find('a',attrs={'class':'rating_people'}).span.text
book_info ={}

book_info['name']=book_name
book_info['author']=book_author
book_info['rating_num'] = int(book_man)
book_info['grade'] = float(book_grade)
print(book_info)

return book_info



if __name__ == '__main__':
all_urls = []
#从第1页到第10页爬取,链接拼接到一起。
for page in range(1,11):
urls = get_book_url(page)
all_urls = all_urls+urls
print('获取到的链接数:',len(all_urls))
out=''
for url in all_urls:
try:
info = get_book_info(url)
except Exception as e:
print(e)
continue
out=out+str(info)+'\n'
with open('douban_book_top250.txt','w') as f: #输出到TXT文件
f.write(out)

image.png

总结

分析页面,找到目标元素所在的tag节点,记录其属性,通过beautifulsoup的find和find_all找到该区域,然后进行相应的提取。这个过程中,要说明一下,使用单线程阻塞爬取250本书的信息,比较耗时,计划后面将会使用多线程进行改进,敬请期待哟。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%