爬虫幼儿园的第一周-cnblog
爬虫幼儿园的第一周
这一周从0开始学爬虫,到找到实习,老己辛苦啦,汇总一下学习成果,再复盘一下面试
-
写在正文的前面
爬虫主要分为两部分获取页面和筛选出想要的内容,网页内容主要分为服务器渲染和客户端渲染。
前者数据在服务器打包好,数据直接在html中,交由浏览器解析。
后者则会通过几次不同的请求,先将html骨架传入,在导入数据在本地浏览器对于二者进行结合,争对这种类型则需要进行抓包拿到数据。我们可以在xhr中找到二次传入的包
请求方式主要有两种,一种为get,另一种为post,这个可以在请求头中找到,这次需要的
反爬
说到请求头就得讲一下反爬,一般来说反爬都在请求头中进行,
最简单的,就是user-agent反爬,由于python文件在访问网站时默认使用的是python的ua,python的ua可以通过用python访问http://httpbin.org/user-agent查看
import requests
resp = requests.get('http://httpbin.org/user-agent')
print(resp.text)
C:\Users\Administrator\python.exe E:\learn\python-project\1.py
{
"user-agent": "python-requests/2.27.1"
}
在headers中添加user-agent,并在访问的时候加上headers = headers,headers可以在浏览器—开发者工具,找一个请求中查看
headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.37"
}
除此之外,请求头中还有一个很重要的是cookie,cookie用于记录本地字符串数据信息,比如登录信息等,添加上cookie可以让服务器识别到登录信息。从登录页面到下一步时,需要连续的访问,所以要使用session
还有就是referer(防盗链),部分网页在反爬时会读取上一页也就是跳转过来的信息,来避免自动化程序的直接访问,我们可以在请求头中添加referer:网址,并且在访问目标网页时使用session(会话)进行访问,这使得我们可以连续的访问。
写完不要忘记加上respone.close()结束访问哦
正则和re提取
我们先来讲一下怎么提取到想要的信息,最基础的就是正则表达式re提取
正则表达式
结论写在前面,一般来说爬虫用到的正则表达式主要就是惰性匹配 .*?,与之对应的是贪婪匹配.。.是匹配任意除换行符之外的所有字符,是修饰元字符出现的次数为0次或更多次,?是修饰前面出现的字符重复0次或一次,这两种匹配方式都为匹配任意字符,正则表达式筛选出想要的方式就是标定字段+目标字段+标定字段,比如
"content":"(?P<content>.*?)","richContent"
这是评论匹配的正则表达式,"content":"如果在古代,周深一定是大祭司。他的歌声让人感觉可以与天与神沟通。","richContent"是获取到页面中的内容,想要获取评论我们可以在获取到的内容中发现,格式是"content":" +评论内容 +","richContent"就可以用前后固定的内容当标记物,获取到想要的内容。(?P
惰性匹配匹配的是最短的符合前后的内容,贪婪匹配则与之相反,匹配最长的符合前后的内容。比如798284,对应的正则表达式为
7.*?8 # 惰性匹配 7.*8 #贪婪匹配
符合的有798和79828两种,惰性匹配结果为798,贪婪匹配则为79828。当然有时候应为标记物的位置和想要获取的值中间可能还有很多别的数据,惰性匹配也可以用于过滤这一部分,只要不做命名的获取就可以了
讲完最需要的,再来看看别的正则匹配的方法吧,
| . | 匹配任意除了换行符之外的所有字符 |
|---|---|
| \w | 匹配字母或数字的下划线 |
| \s | 匹配任意的空白符(空格,换行符,回车) |
| \d | 匹配数字 |
| \n | 匹配换行符 |
| \t | 匹配一个制表符 |
| ^ | 匹配字符串的开始 |
| $ | 匹配字符串的结尾 |
| \W | 匹配非字母或数字或下划线 |
| \D | 匹配非数字 |
| \S | 匹配非空白符 |
| a|b | 匹配字符a或字符b |
| () | 匹配括号内的表达式,也表示一个组 |
| [...] | 匹配字符组中的字符(可以用-表示连续比如[a-z]表示匹配所有a-z的字符) |
| [^...] | 匹配除了字符组中字符的所有字符 |
| 量词 | 控制前面的元字符出现的次数 |
|---|---|
| * | 重复0次或更多次 |
| + | 重复一次或更多次 |
| ? | 重复0次或一次 |
| 重复n次 | |
| 重复n次或更多次 | |
| 重复n到m次 |
re提取
(import re)
findall:匹配所有符合正则的内容并返回列表
lst = re.findall(r"\d+", "我的电话是10086,我女朋友的电话是10010")
finditer:匹配字符串中所有的符合正则的内容并返回迭代器,从迭代器中拿到内容需要调用group()方法(最常用)
it = re.finditer(r"\d+", "我的电话是10086")for i in it: print(i.group())
search:匹配字符串中第一个符合正则的内容并返回match对象,如果没有匹配到,则返回None
s = re.search(r"\d+", "我的电话是10086,我女朋友的电话是10010")
match:从头开始匹配,如果开头没匹配到则报错
s = re.match(r"\d+", "a10086,我女朋友的电话是10010")
complie:预加载正则表达式的作用是提高效率,避免每次都要编译正则表达式
obj = re.compile(r"\d+")
re.S :让.能匹配换行符
obj = re.compile(r'.*?<span>(?P<num>.*?)</span>', re.S)
(?P<分组名字>正则)可以对正则匹配的内容中进一步提取内容
用(?P<...>.*?)对匹配项目进行包裹,?P进行重命名,用it.group("...")进行输出匹配
https://docs.python.org/zh-cn/3/library/re.html
这里附上re的中文文档
BeautifulSoup
(from bs4 import BeautifulSoup)
BeautifulSoup查找html文件非常方便,基本格式是(标签,属性=值),html主要有标签,属性,属性值几个特点
<h1 align="center">i don't love you</h1>
在这里h1是标签,align是属性,而center是属性值,注意,一个标签可能有多个属性和属性值,也可能和别的语句有重复的标签属性和属性值,所以我们在筛选的时候记得注意查看和选择我们的筛选条件。
</h1> <img src="xxx.jjpg"/>
语句可能有额外闭合和自带闭合两种格式,额外闭合以/为标志,作为这个段落的结束标签,这意味着我们可以通过这个方式找到对应的段落层次,但是也要注意不是所有的html语句都有额外闭合。这有助于我们对于需要文字位置的判断。
使用BeautifulSoup主要用的的语句有两个一个是find,另一个是find_all
格式为find(标签,属性=值) 和 find_all(标签,属性=值)
二者的区别主要在于,find只查找符合条件的第一个值,而find_all查找所有符合条件的值。find_all返回的数据为ResultSet,包含了所有符合查找条件的元素。我们可以像操作列表一样对 ResultSet 进行索引、迭代等操作。
所以在对find_all结果进行操作的时候,有时需要带上[0],否则会报错
但是一旦我们进入实操的时候可能会碰到,有时候目标的属性名和python自带的关键字相同的情况这时候有两种处理方式
第一、在原有的属性名后添加"_",比如"class"->"class_"
第二就是使用字典进行替换比如attrs={'class': 'hq_table'},属性为key,值为value
注:尽量不要使用空的属性作为筛选条件
https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/
这里附上beautiful soup的中文文档链接,可以看到更多详细的信息。
Xpath
(from lxml import etree)
然后到了我们最后的Xpath
xpath和前面的不太一样,它更像一个链表的方式,从最外层一层层匹配下来,前面在beautiful soup中讲到了标签,xpath使用的是一层层标签匹配下来,类似于路径。
我们可以在网页-开发者工具-元素中右键标签,选择复制-复制xpath或者复制完整xpath直接获取到路径。
有时候我们不一定一次就直接拿到想要的数据,所以在下一次xpath中可以用"."开头表示延续上一个的路径进行下一步筛选。
使用text()可以把语句中间文本块单独的提取出来。
注意:同一级中可能有不同的同标签名语句,类似于列表存储,但是列表从1开始

浙公网安备 33010602011771号