[TOC]
Requests库
1 | resp = requests.get(url, params={}, headers={}) |
- 使用get方式发起对一个页面的访问请求,对requests方法二次封装。
- params:用字典的形式来传参,可以动态地修改请求参数,输出结果和直接在url上拼接是一样的。
- headers:用字典的形式来添加请求头信息,如”user-agent”、”cookie”等登录信息。
- 返回response对象,包含了爬虫返回的全部内容。
Response对象
1 | r.status_code # HTTP请求返回的状态码 |
- 若返回内容中包含乱码,需要重新设置r.encoding。常用r.encoding = r.apparent_encoding。
bs4库
用来解析各种标签树的库
基本元素
- 标签:
- 标签的名字:
.name - 标签的属性:
.attrs,返回字典类型。 - 标签内非属性字符串:
.string,若有多个则返回none。 .text,若有多个则连接后返回str。
遍历元素
下行遍历
- .contents:返回子结点的列表,也包含字符串类型如’\n’、’\r’等。
- .children:返回子结点的迭代类型
- .descendants:返回子孙结点的迭代类型
上行遍历
- .parent:返回父亲标签
- .parents:返回先辈标签的迭代类型
平行遍历(同一个父节点下,包含字符串类型)
.next_sibling:返回按照HTML文本顺序的下一个平行结点标签
.previous_sibling:返回按照HTML文本顺序的上一个平行结点标签
.next_siblings:返回后续所有平行结点的标签的迭代类型
.previous_siblings:返回前续所有平行结点的标签的迭代
soup属性
1 | from bs4 import BeautifulSoup |
可以用soup来获取该标签的第一个
1 | soup.title |
soup函数
1 | lis = soup.find_all(name, attrs, recursive, string, **kwargs) |
- name:标签名的检索字符串或字符串列表,可以传入正则表达式
- attrs:标签属性值的检索字符串或字典
- recursive:默认为True,False表示只在根节点的儿子结点中找。
- string:要检索的非属性的字符串值
re正则表达式库
语法
正则表达式语法由字符和操作符构成。
单个字符
.表示任意单个字符。[abc]表示a、b、c,[a-z]表示a-z的单个字符,对单个字符给出取值范围 。[^abc]表示非a非b非c的单个字符,对单个字符给出排除范围。\d表示单个数字,等价于[0-9]。\w表示单个单词字符,等价于[A-Za-z0-9_]。
- 字符扩展
*表示前一个字符0或无限次扩展,+表示前一个字符1或无限次扩展,?表示前一个字符0或1次扩展。{m}扩展前一个字符m次,{m, n}扩展前一个字符m至n次。
最小匹配
*?、+?、??、{m, n}?。- 当一个操作符可以匹配不同长度的时候,可以在这个操作符后面加一个
?来获得最小匹配的结果。
其他
^abc表示abc且在一个字符串的开头,abc$表示abc且在一个字符串的结尾。(abc|def)表示abc、def,左右表达式任意一个。
经典正则表达式
- 由26个字母组成的字符串:^[A-Za-z]+$
- 由26个字母和数字组成的字符串:^[A-Za-z0-9]+$
- 整数形式的字符串:^-?\d+$
- 正整数形式的字符串:
^[0-9]*[1-9][0-9]*$ - 中国境内邮政编码:[1-9]\d{5}
- 中文字符:[\u4e00-\u9fa5]
- 国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
- IP地址
- \d{1, 3}. \d{1, 3}. \d{1, 3}. \d{1, 3}
- 0-99:[1-9]?\d;100-199:1\d{2};200-249:2[0-4]\d;250-255:25[0-5]
re库
re库默认采用贪婪匹配方式,即输出匹配最长的字串。
1 | match = re.search(patten, string, flags=0) # 匹配一个字符串,不限定始末 |
- patten:正则表达式,string:待匹配的字符串,以上五个函数都有这两个参数。
- flags
- re.I:忽略大小写
- re.M:针对^操作,每行都可以作为匹配起始位置
- re.S:针对.操作,可以匹配所有字符
maxsplit:最大分割数,剩余部分作为最后一个元素输出
repl:替换匹配字符串的字符串
- count:最大替换次数
- match对象
- .group(0) 获得匹配后的字符串
- .start() 匹配字符串在原始字符串的开始位置
- .end() 匹配字符串在原始字符串的结束位置
实战
爬取淘宝商品及价格
获取淘宝某商品搜索结果页面
1
2url = 'https://s.taobao.com/search?q=' + goodname # goodname为某商品名
r = requests.get(url, headers)值得注意的是,在headers中需要设置cookie信息,可以手动登录淘宝后把cookie信息复制过来。
解析HTML
得到搜索结果HTML后,发现商品名字和价格分别在”raw_title”和”view_price”中,因此可以使用正则表达式来提取相关信息。
1
2nlt = re.findall(r'"raw_title":".+?"', page) # 包含商品名信息列表
plt = re.findall(r'"view_price":".+?"', page) # 包含价格信息列表去掉无用信息,得到商品名和价格列表
1
2for i in range(len(nlt)):
ilt.append([eval(nlt[i].split(':')[1]), eval(plt[i].split(':')[1])]保存结果
使用file.write()按照一定格式写入文件。
tips
- 其实还可以观察到淘宝的翻页,只需要在url后加上
&s=44,s的值加44实现一次翻页。 - 整个过程使用requests库爬取HTML页面,再使用re库检索到有用信息,最后对有用信息加工存储。
- requests每次只能爬取指定url的页面,因此需要事先观察要爬取网页的url信息。
爬取笔趣阁的小说
获取指定书号的小说首页HTML(同上)
解析HTML
与爬取淘宝url基本保持不变的例子不同,一本小说有数百章节,每个章节都是一个独立的页面,因此需要事先在首页中获取到所有章节的url信息。
通过观察得到所有章节的url都存放在属性class=listmain的div标签中的a标签中,因此我们使用BeautifulSoup库来检索到这些a标签。
1
2soup = BeautifulSoup(html,"html.parser")
alist = soup.find("div",attrs={"class":"listmain"}).find_all("a")然后处理得到真正的url
1
chaptLinks.append(a.attrs["href"].split("/")[-1])
接下来对每个章节页面进行分析,提取标题和正文。观察到标题在title标签中,正文在属性id=content,class=showtxt的div标签中。
1
2
3title = soup.find("title").string.split("_")[0].strip()
text = soup.find("div",attrs={"id":"content","class":"showtxt"}).text
text = re.sub("\s+", "\n", text) # 用一个换行符替换1~多个空格
保存结果(同上)
tips
- 这个例子中使用了BeautifulSoup库来对标签信息检索,也用到了re库来对文本信息检索。