爬虫从入门到放弃(一)
分享一波爬虫从0.1到1的实战经验以及总结,特开此系列记录📝
为什么说是从0.1而不是0呢,因为当前仅有一些爬虫的基础知识而已,对于框架与实战经验的认知均为0。所以要是大佬打开了这篇文章,可能要让你失望了哈哈哈
每一个项目基本上都是边学边做,因为在实战中有很多坑,太少的知识储备让我在坑里爬不上来...希望各位看官也能从中学到东西!
ok,废话不多说,来看看爬虫坑的第一个实战项目-资讯爬取
目标地址:http://auto.gasgoo.com/comment/C-302-303-304/1
需要提取的数据:文章标题、文章摘要
要求:
- 只能用requests、re完成
- 爬取所有页码数的数据
- 提取的数据存入mysql
好了,清楚了要求以及需求,开始分析如何进行爬取。
根据聚焦爬虫流程,大致可分为四步
- 从url中提取响应内容
- 分析响应内容(页面),提取url,添加至urllist
- 从urllist中提取响应内容,提取数据
- 数据入库
1.从url中提取响应内容
爬取第一页试试
import requests
import re
url = "http://auto.gasgoo.com/comment/C-302-303-304/1"
content = requests.get(url).content.decode()
print(content)
ok,不需要添加headers即可爬取下来,可以开始分析怎么去获取我们的urllist了。
在分析之前,分享个小知识,我们获取页面响应内容有两个属性,response.text和response.content。那么一般使用哪个呢?
response.text 和response.content的区别
- response.text
- 类型:str
- 解码类型: 根据HTTP头部对响应的编码作出有根据的推测,推测的文本编码
- 如何修改编码方式:response.encoding=”gbk”
- response.content
- 类型:bytes
- 解码类型: 没有指定
- 如何修改编码方式:response.content.deocde(“utf8”)
而根据经验所得,怎么才能做到100%的解决乱码问题,按照以下步骤即可:
- 先使用decode()来尝试解码, 现在国内80%网站都是用utf-8进行编码的
- 如果上面面没有解决乱码问题,就指定GBK的编码方式, 个别网站使用的是GBK
- 举例(人民网): http://www.people.com.cn/
- 如果指定GBK还不行,就request的自动推断功能了,通过text 属性获取
总结:更推荐使用response.content.deocde()
的方式获取响应的html页面
2.分析响应内容(页面),提取url,添加至urllist
点击【下一页】,查看url是否会有变化
发现url的末端变化了,变成了2,手动更改为1000,回车,跳转至1000页,那么确定了url,可以开始构建我们的urllist了。
import requests
import re
class Spider_news():
#定义一个爬虫类
baseurl = "http://auto.gasgoo.com/comment/C-302-303-304/{}"
def __init__(self):
#初始化方法
content = requests.get(url=self.baseurl.format(1)).content.decode()
self.end_page = re.search("href='/comment/C-302-303-304/(\d+)'>末页</a></div>",content).group(1)
#print(self.end_page)
def get_urllist(self):
#生成urllist,从中提取url
# urllist = []
# for i in range(int(self.end_page)+1):
# urllist.append(self.baseurl.format(i))
#用列表推导式更简洁一些
return [self.baseurl.format(i) for i in range(1,int(self.end_page)+1)]
def run(self):
#启动爬虫主流程
pass
if __name__ == '__main__':
spider = Spider_news()
spider.run()
这样第二步骤的代码已经完成了,拿到了urllsit。
3.从urllist中提取响应内容,提取数据
因为拿到了urllsit,所以每一页的响应内容都可以拿到了,接下来就是用re去提取我们想要的数据。注意了,坑来了!
我们可以看到第一页的前两条资讯,标题和摘要的html格式都是一致的,所以使用以下正则去提取我们需要数据
for i in urllist:
html = self.get_content(i)
abstract = re.findall('<p class="details">(.*?)/p>',html)
title = re.findall('shtml">(.*?)</a></h2>',html)
print(abstract)
print(title)
打印出来看一下
可以发现,这正则并不能很好的匹配到我们想要的数据,看以下第三行中出现的a标签是怎么回事,根据上面代码我们知道,是第二页中的数据提取有问题,把a标签内容复制到第二页的网页源代码,看看这条正则怎么会匹配到这个a标签的。
可以看到,第二页的这条资讯的摘要,和第一页中的摘要html格式是不一样的,无法使用这条正则去匹配,那么问题来了,正则应该怎么去修改呢?
看到这里,你们可以自己动手试试,看看能不能写出匹配到这两种格式的正则表达式。
到最后你会发现,一条正则是不可能匹配得了所有页面的资讯摘要。。。
因为有非常多不一样的格式,所以这里用正则去做就是一个坑!用xpath是最好的选择,这里非要用正则解决的话,就只能写两条去匹配,然后遍历得到的列表,再加进去一个新的摘要列表。
abstract_re = '<p.*?>([\s\S]*?)<a target="_blank" href="/[aN]'
abstract_re = '<p class="details">(.*?)/p>'
4.最后一步,数据入库
这边用的是pymysql连接mysql数据库
操作数据库的五个步骤:
- 连接数据库
- 获取游标
- 执行sql语句
- 提交事务
- 关闭游标,关闭数据库连接
import pymysql
def save_content(data):
db = pymysql.connect("localhost", "root", "123456", "spider_data") # 打开数据库连接
cursor = db.cursor() # 获取一个光标
cursor.execute("INSERT INTO tencent__video_content(评论) values (%s)", (data)) # 执行sql语句
db.commit() # 涉及写操作要注意提交
cursor.close()# 关闭游标/连接
db.close()
那么先来总结一下,这次所遇到的坑。
- requests.content 和 requests.text的区别
- 正则提取的数据处理
.
不支持匹配\n,导致有换行符的数据没匹配到- 使用正则
\s\S
当作.
去使用 - html转义字符的处理,比如\t什么的
- 使用
str.replace
方法替换掉这些影响提取数据的字符
- 使用
- 数据库入库中文乱码
- 数据库的字符集需要设置为utf8
- 字段字符集都需要设置为utf8mb4
- 排序规则均为utf8_general_ci
ok,基本思路和遇到的坑都放上来了,完整代码就你们自己去完成吧,挺简单的。这次主要是为了学习基本爬虫的思路,入门的第一个小项目结束!!!