基于Requests的Python爬虫入门实例------爬取豆瓣图书排行榜的前25本图书(小白福利)

    xiaoxiao2025-02-10  19

     话不多说,先上代码: 

    # -*- coding:utf-8 -*- import sys import requests import lxml from bs4 import BeautifulSoup from requests.cookies import RequestsCookieJar #设置请求头,伪装成浏览器 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'} #设置目标url url = 'https://book.douban.com/top250?start=0' #使用requests模块提供的的Http服务 resp = requests.get(url, headers = headers) #如果目标网页编码与本地不一致,修改本地默认编码方式(防止输出中文乱码) if sys.getdefaultencoding() != resp.encoding: reload(sys) sys.setdefaultencoding(resp.encoding) #使用BeautifulSoup来分析和定位Html中我们所需的内容 soup = BeautifulSoup(resp.text,'lxml') #构建BeautifulSoup对象 #创建记录数据的文件 file_out = "C:\\out.txt" #Windows下文件名分隔符为 " \\ " i = 0 #使用BeautifulSoup中的select方法(返回的是list对象)获取所需内容 name_list = soup.select('tr > td > div.pl2 > a') #设置select方法中的参数可以用XPath也可以直接通过标签结点层层递进 #定义一个结果列表 result_list = ["豆瓣图书排行榜"] #定义一个查重并更新列表的方法,如果当前元素已存在于列表中则不做更新操作 def FindIfRepeat (OldList,item): if item not in OldList: NewList = OldList.append(item) return NewList else: return OldList #用for循环遍历soup对象返回的列表 for name in name_list: i += 1 outcomeList = name.get_text().strip().split() #对于返回的结果进行分段并去掉两端空格 for outcome in outcomeList: m = len(outcomeList) if m >= 2 : #判断是否有对书的描述字段 #使用迭代器遍历outcomelist Newoutcome = "" it = iter (outcomeList) for x in it: Newoutcome = Newoutcome + str(x) + " " Newoutcome = Newoutcome.split(':',1) #对于获取的结果做格式化处理 name_format = "Top{rank},书名《{name}》,描述:{description}".format(rank = str(i),name = Newoutcome[0],description=Newoutcome[1]) FindIfRepeat(result_list,name_format) #调用查重函数进行查重更新结果列表的操作 else: name_format = "Top{rank},书名《{name}》,描述:暂无".format(rank = str(i),name = outcomeList[0]) FindIfRepeat(result_list,name_format) #将结果写入文件中 for i in range(len(result_list)): with open (file_out , "a+" ) as f :#使用with...open格式打开文件的好处在于不用手动关闭文件 f.write(str(result_list[i]) + '\r\n')

      输出结果:

    豆瓣图书排行榜 Top1,书名《追风筝的人》,描述:暂无 Top2,书名《解忧杂货店》,描述:暂无 Top3,书名《小王子》,描述:暂无 Top4,书名《白夜行》,描述:暂无 Top5,书名《围城》,描述:暂无 Top6,书名《三体 》,描述: “地球往事”三部曲之一 Top7,书名《嫌疑人X的献身》,描述:暂无 Top8,书名《活着》,描述:暂无 Top9,书名《挪威的森林》,描述:暂无 Top10,书名《百年孤独》,描述:暂无 Top11,书名《红楼梦》,描述:暂无 Top12,书名《看见》,描述:暂无 Top13,书名《平凡的世界(全三部)》,描述:暂无 Top14,书名《三体Ⅱ 》,描述: 黑暗森林 Top15,书名《三体Ⅲ 》,描述: 死神永生 Top16,书名《不能承受的生命之轻》,描述:暂无 Top17,书名《达·芬奇密码》,描述:暂无 Top18,书名《我们仨》,描述:暂无 Top19,书名《天才在左 疯子在右 》,描述: 国内第一本精神病人访谈手记 Top20,书名《简爱(英文全本)》,描述:暂无 Top21,书名《哈利·波特与魔法石》,描述:暂无 Top22,书名《明朝那些事儿(壹) 》,描述: 洪武大帝 Top23,书名《傲慢与偏见》,描述:暂无 Top24,书名《目送》,描述:暂无 Top25,书名《恶意》,描述:暂无

    不知道你们看懂了没,如果你是小白,那就请你往下看代码详解,大佬请绕道,哈哈!

    代码详解

    首先:你得知道一个制作一个爬虫的大概流程如下:

    获取目标URL→通过requests(也可以使用urllib)等模块建立HTTP连接获得网页的返回内容➡通过BeautifulSoup(或者lxml)等模块解析HTML文档寻找所需内容➡遍历BeautifulSoup对象,输出目标内容到控制台或者指定文件。

    准备工作:导入相关库和设置编码方式(很重要,爬虫最常见错误就是抓取回来的内容乱码,好习惯很重要哦!)

    # -*- coding:utf-8 -*- import sys import requests import lxml from bs4 import BeautifulSoup from requests.cookies import RequestsCookieJar

    设置请求头,将爬虫伪装成浏览器(有些网站设置了反爬机制,不设置这个有可能爬虫没法用)

    #设置请求头,伪装成浏览器 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'}

    设置请求头方法参考:https://blog.csdn.net/FloatDreamed/article/details/79208719

    设置URL和创建requests对象

    #设置目标url url = 'https://book.douban.com/top250?start=0' #使用requests模块提供的的Http服务 resp = requests.get(url, headers = headers)

    URL很简单,就是要爬取的目标网页。

    创建requests对象,URL参数是必须的,其他的headers以及待会儿会讲到的cookie和proxies(代理)是可选的。有了requests对象,就可以使用它的Get 和Post方法了,如果学过Java,就应该明白这两个功能对于日常的网络服务是完全够用了的 

    Get方法用于向服务器请求并得到从服务器返回的数据(response对象),Post方法用于提交表单,向服务器更新数据等操作。

     Requests库的详细用法参考:https://blog.csdn.net/iloveyin/article/details/21444613

    中文乱码的解决方法

    前面提到了爬虫最常见的问题是返回的数据中文乱码,对于爬虫小白来说这样的问题几乎不可避免,不过别担心,我这里有好几种解决中文乱码的方法,总有一款适合你。

    方法一:(适用于Pycharm下编程)

    先在代码头设置编码方式为 " UTF-8" ,UTF-8 是保存中文字符的通用代码。然后,如图所示的操作一般都能解决中文乱码问题。

     其他方法参考以下链接:

    https://blog.csdn.net/weixin_42134789/article/details/82904741

     使用BeautifulSoup解析HTML文档

    #使用BeautifulSoup来分析和定位Html中我们所需的内容 soup = BeautifulSoup(resp.text,'lxml') #构建BeautifulSoup对象 #使用BeautifulSoup中的select方法(返回的是list对象)获取所需内容 name_list = soup.select('tr > td > div.pl2 > a') #设置select方法中的参数可以用XPath也可以直接通过标签结点层层递进

     写爬虫程序最关键的部分在于如何从网页中提取我们想要的内容,这里用到了一个强大的HTML解析库-----BeautifulSoup,通过BeautifulSoup对象可以很轻松的通过select或是find_all方法从繁杂的HTML中提取到有用的信息,其中最难理解的应该是select等方法中的参数怎么获取,不着急,下面就手把手的教你:

    以下全程使用chrome浏览器,其他浏览器的操作步骤类似:

    第一步:使用浏览器打开目标网页,F12进入开发者模式

    第二步:点击图中所示按钮,再点击所需要定位的内容

     第三步:分析复制下来的位置信息

    #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > div.pl2 > a

    其实这看似复杂的东西不过就是HTML文档中书名标题所在的位置,是一层层的标签嵌套关系,我们的select方法就是要靠这个参数来定位到HTML文档中书名标题所在位置,然后通过soup.text 把书名标题标签里的内容提取出来,然后再输出到控制台或者写入文件中,我们爬虫的作用就达到了。

     当然,复制过来的东西还不能直接用,因为这只是一个标题的,而我们要的是TOP25,所以要把具体的部分去掉,可以同样的方法多定位几个标题,多对比几次,找出共同的部分。

    #一开始拿到的《追风筝的人》的定位是 #content > div > div.article > div > table:nth-child(2) > tbody > tr > td:nth-child(2) > div.pl2 > a #这是图中《解忧杂货店》的定位 #content > div > div.article > div > table:nth-child(4) > tbody > tr > td:nth-child(2) > div.pl2 > a #这是中《小王子》的定位 #content > div > div.article > div > table:nth-child(6) > tbody > tr > td:nth-child(2) > div.pl2 > a

     把变化的地方去掉,留下共同的部分,tr前面都一样,累赘删掉了(后面有个div.p12是整个HTML中唯一,前面的父标签就可以省去了。)

    简化后的结果如下:

    > tr > td:nth-child(2) > div.pl2 > a #进一步简化 > tr > td > div.pl2 > a

    这里的分析只是一个参考,select中还可以填入其他的参数,像是正则表达式什么的,也可以使用find_all方法寻找内容,有关BeautifulSoup的详细使用方法可以参考:https://blog.csdn.net/qq_21933615/article/details/81171951

    解析HTML文档的这部分内容是爬虫的核心,这些定位参数决定爬虫能否爬取到所需信息,一定要细心呐!

     剩下的代码就是常规的东西了,是根据前面具体的返回结果的格式来设计如何美化输出,可以先把爬回来的东西输出到控制台,看看效果,然后再做相应的调整。

    #把返回的内容先输入到控制台看看效果 for name in name_list: i += 1 print(i,name.get_text().strip())

     控制台显示的效果如下:

     还行,中间有一大段空格,可以用str.format()函数进行格式化输出

    #用for循环遍历soup对象返回的列表 for name in name_list: i += 1 outcomeList = name.get_text().strip().split() #对于返回的结果进行分段并去掉两端空格 for outcome in outcomeList: m = len(outcomeList) if m >= 2 : #判断是否有对书的描述字段 #使用迭代器遍历outcomelist Newoutcome = "" it = iter (outcomeList) for x in it: Newoutcome = Newoutcome + str(x) + " " Newoutcome = Newoutcome.split(':',1) #对于获取的结果做格式化处理 name_format = "Top{rank},书名《{name}》,描述:{description}".format(rank = str(i),name = Newoutcome[0],description=Newoutcome[1]) FindIfRepeat(result_list,name_format) #调用查重函数进行查重更新结果列表的操作 else: name_format = "Top{rank},书名《{name}》,描述:暂无".format(rank = str(i),name = outcomeList[0]) FindIfRepeat(result_list,name_format) #将结果写入文件中 for i in range(len(result_list)): with open (file_out , "a+" ) as f :#使用with...open格式打开文件的好处在于不用手动关闭文件 f.write(str(result_list[i]) + '\r\n')

     美化之后的效果:

     哈哈,强迫症的我看着就舒服多了。。。

    知识拓展

     

    使用proxies代理

    前面提到了,有些网站会有反爬机制,要是一不小心被封了IP,那多尴尬呀!不慌,这篇博客就是给小白们提供福利的,下面就是使用代理的方法。

    #使用动态代理,防止被封IP proxies = { "http": "http://149.129.70.226:8434", "https": "http://218.28.238.165:8267", } #使用requests模块提供的的Http服务 resp = requests.get(url, headers = headers,proxies = proxies)

    使用动态代理其实至于要定义一个参数proxies,然后把IP加进去,再加到requests请求方法中就行了鸭!easy?

    不不不不不,其实你在使用的时候可能会碰到各种连接不上的情况,比如下面这种:

     看吧,没这么简单吧?其实这是因为我这里用的IP地址是网上找到的免费IP,用的人多了,被目标网站封掉了(呜呜呜~),所以爬虫还是有风险的哦,不要轻易用自己的电脑IP反复爬取同一个网站哦!网上的免费IP很多,可以参考这个网址http://www.data5u.com/上面有10个免费IP可以用,不定期更新,一个不行就试试另一个呗~

    最后提醒一点:爬取https的网站就要用HTTPS的IP哦!不然还是可能会连不上~

    2.在请求头中加入cookie或者使用session保持登陆

    有时候爬取某些网站的时候需要先登录,但是呢,我们爬取数据的时候不可能每爬取一次就重新登录一次,那样就太繁琐了,所以就要用到cookie(小甜饼),这可是浏览器最爱的美食呢!里面记录了用户的登录信息,我们只需要把它加到我们的请求头里就不用每次都登录啦!因为这相当于告诉服务器,“ 对,我胡汉三又回来啦!" ,服务器可以通过cookie知道当前请求的客户端已经登录过了。

    #方法一 #首次使用cookie时可以先打印出浏览器中保存的cookie格式,然后再设置相应的cookie resp = request.get(url,headers = headers) print(resp.cookies) #设置cookie(保存在本地端的用户信息) cookie_jar = RequestsCookieJar() #创建一个cookiejar对象,urllib中也有类似的东西,作用是生成一个cookie对象 cookie_jar.set(name = " root " ,password =" 123456 " ) #set方法设置cookie的具体内容 response = requests.get("url", cookies=cookie_jar) #方法二 #使用session(会话)维持登陆(相当于保存在服务器端的cookie) session1 =requests.session() #创建session对象 resp = session1.get("url",headers = headers) #再用session对象进行HTTP请求,这样就可以维持登录状态 #方法一和二 只用一种就行

    —————————————————————————   END ————————————————————————————

    最新回复(0)