Python爬虫实践~BeautifulSoup+urllib+Flask实现静态网页的爬取

爬取的网站类型:

    论坛类网站类型

涉及主要的第三方模块:

    BeautifulSoup:解析、遍历页面

    urllib:处理URL请求

    Flask:简易的WEB框架

介绍:

        本次主要使用urllib获取网页数据,然后通过BeautifulSoup进行页面解析,返回json结构的数据。

功能点:

  • urllib根据URL通过GET方式获取网页内容;

  • 通过JSON文件配置

  • 解析页面结构,返回JSON结构的数据

  • 提供REST服务进行调用

     

特点:

1、提供数据描述服务,总页面,每页条数,总条数;

2、增量请求数据,只获取当前时间和上次请求时间之间的数据;

3、控制请求时间间隔,防治IP被封杀

4、分页数据请求

5、修改请求关键字,并记录上次的请求关键字

 

主要代码结构:

- 公共请求端封装

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from urllib import request
from urllib.parse import quote
import string
import requests

# 静态页面基类
class StaticBase():
    # 获取网页内容
    def __getHTMLText(self,url,code="utf-8"):
        try:
            r = requests.get(url)
            r.raise_for_status()
            r.encoding = code
            return r.text
        except:
            return ""
    # get方式请求数据
    def getUrl(self,url,code='utf-8'):
        url = quote(url,safe=string.printable)
        req = request.Request(url)
        req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36')
        with request.urlopen(req) as f:
            print('Status:',f.status,f.reason)
            return f.read().decode(code)

#s = StaticBase()
#print(s.getUrl('http://www.baidu.com/','utf-8'))

- 配置文件

{
   "host": "http://shangyu.108sq.cn", 
   "base_url": "http://shangyu.108sq.cn/shuo/search?sertype=4", 
   "key_words": "污染", 
   "page_size": 30, 
   "search_key": "", 
   "last_request_time": 1562142204.149511, 
   "request_gap": 60
  }

- 解析服务

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from bs4 import BeautifulSoup
from datetime import datetime
import json
from common.staticBase import StaticBase

class Shangyh108(StaticBase):

    __config_file = "config.json"   #配置文件
    __text = ""                     #解析的网页内容
    __config_dict = {}              #配置集合
    __url = ""                      #请求的URL
    __keywords = ""                 #关键字
    __last_request_time = 0         #上次请求时间
    # 构造函数
    def __init__(self):
        self.__config_dict = self.__getConfig()
        # 查询关键字
        if len(self.__config_dict['search_key']) >0 :
            self.__keywords = self.__config_dict['search_key']
        else:
            self.__keywords = self.__config_dict['key_words']
        self.__url = self.__getUrl()
    # 获取网页内容
    def getText(self):
        print(self.__url)
        self.__text = StaticBase.getUrl(self,self.__url)

    # 获取第一页内容
    def getFirstPageText(self,url=''):
        if self.checkRquestTime():
            if len(url)==0 :
                url = self.__getUrl()
            self.__text = StaticBase.getUrl(self,url)
            return self.parseHTML()
        else:
            print("操作频繁请稍后重新")
    # 获取下一页
    def getNextPage(self,url):
        url = self.__config_dict['host']+url
        print(url)
        self.__text = StaticBase.getUrl(self,url)
        return self.parseHTML()

    # 为防止请求对服务器造成太大压力,控制请求的时间间隔,最少为5分钟
    def checkRquestTime(self):
        request_gap = self.__config_dict['request_gap']
        last_request_time = self.__config_dict['last_request_time']
        dt_now = datetime.now().timestamp()
        self.__last_request_time = last_request_time  # 记录上次请求的时间,为了获取阶段性的数据
        if last_request_time == 0:  #第一次请求,直接通过
            last_request_time = dt_now
        elif last_request_time+request_gap > dt_now:
            print("请求过度频繁,请稍后重试")
            return False
        else:
            last_request_time = dt_now

        self.__setConfig('last_request_time',last_request_time)
        return True

    # 获取网页描述信息
    def getDesc(self):
        self.getText()
        soup = BeautifulSoup(self.__text,'html.parser')
        obj_count = soup.select('.count')[0]
        count_str = str(obj_count.string).replace("(共","").replace("条)","")
        count = int(count_str)
        pageSize = int(self.__config_dict['page_size'])
        host = self.__config_dict['host']
        if count % pageSize == 0 :
            pages = count//pageSize
        else:
            pages = count // pageSize + 1
        desc = {}
        desc['host'] = host
        desc['count'] = count
        desc['page_size'] = pageSize
        desc['total_page'] = pages
        # 增加分页的URL
        if pages > 0 :
            pageUrls = soup.select(".TCPage__middle > a")
            page_url = []
            for i in range(len(pageUrls)-1) :
                tag = pageUrls[i+1]
                page_url.append(tag['href'])
            desc['page_url'] = page_url
        return json.dumps(desc,ensure_ascii=False)

    # 解析网页内容
    def parseHTML(self):
        soup = BeautifulSoup(self.__text, 'html.parser')
        list_li = soup.select('.TCSayList .TCSayList_li')
        data_list = []
        for i in range(len(list_li)):
            item = {}
            temp = list_li[i]
            publish_time = temp.select('.TCSayList_li_time')[0]
            int_dt = int(publish_time['data-time'])

            if self.__last_request_time == 0 or self.__last_request_time < int_dt :
                # 发布时间
                item['publish_time_long'] = publish_time['data-time']
                item['publish_time_str'] = datetime.fromtimestamp(int(publish_time['data-time'])).strftime(
                    '%Y-%m-%d %H:%M:%S')

                # 数据标签
                item['data-tag'] = temp['data-tag']
                # 用户
                author = temp.select('.TCSayList_li_author')[0]
                item['author_name'] = author.string
                item['author_url'] = author['href']

                # 标题
                if len(temp.select('.TCSayList__title a')) >0:
                    title = temp.select('.TCSayList__title a')[0]
                    item['title'] = title.string
                    item['link_url'] = title['href']
                # 内容
                item['content'] = temp.select('.TCSayList_li_content')[0]['data-short']

                data_list.append(item)
        return data_list
    # 获取请求配置信息
    def __getConfig(self):
        with open(self.__config_file, "r",encoding="utf-8") as load_f:
            load_dict = json.load(load_f)
        return load_dict
    # 设置配置项
    def __setConfig(self,key,value):
        self.__config_dict[key] = value
        print(self.__config_dict)
        with open(self.__config_file,'w',encoding="utf-8") as f:
            f.write(json.dumps(self.__config_dict,ensure_ascii=False))

    def getKeywords(self):
        self.__keywords = input("请输入查询的关键字,多个关键字用“+”连接,默认关键字:环保+污染+投诉,使用默认关键字可直接按Enter:")
        if len(self.__keywords) == 0:
            self.__keywords = self.__config_dict['key_words']
        else:
            self.__setConfig("search_key",self.__keywords)

    # 获取请求的URL
    def __getUrl(self):
        base_url = self.__config_dict['base_url']
        # 组装查询参数
        url = base_url + "&key=" + self.__keywords
        return url

- REST服务端(目前服务没有暴露很多,但相应服务实现都已经实现)

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
from flask import Flask,jsonify,abort,request
from changshuo108.shangyu.Shangyh108 import Shangyh108

app = Flask(__name__)
# 支持中文
app.config['JSON_AS_ASCII'] = False
shangyue = Shangyh108()
@app.route('/shangyu108/api/desc',methods=['GET'])
def get_desc():
    return shangyue.getDesc()

@app.route('/shangyu108/api/first_page',methods=['GET'])
def get_firstPage():
    return jsonify({'data':shangyue.getFirstPageText('')})

@app.route('/shangyu108/api/page',methods=['POST'])
def get_article():
   if not request.json or not 'url' in request.json:
      abort(400)
   print(request.json['url'])
   return jsonify({'data':shangyue.getNextPage(request.json['url'])})

if __name__ == '__main__':
    app.run(debug=True)

 

爬取的网站类型:

    论坛类网站类型

涉及主要的第三方模块:

    BeautifulSoup:解析、遍历页面

    urllib:处理URL请求

    Flask:简易的WEB框架

介绍:

        本次主要使用urllib获取网页数据,然后通过BeautifulSoup进行页面解析,返回json结构的数据。

功能点:

  • urllib根据URL通过GET方式获取网页内容;

  • 通过JSON文件配置

  • 解析页面结构,返回JSON结构的数据

  • 提供REST服务进行调用

     

特点:

1、提供数据描述服务,总页面,每页条数,总条数;

2、增量请求数据,只获取当前时间和上次请求时间之间的数据;

3、控制请求时间间隔,防治IP被封杀

4、分页数据请求

5、修改请求关键字,并记录上次的请求关键字

 

主要代码结构:

- 公共请求端封装

#!/usr/bin/env python # -*- coding:utf-8 -*-from urllib import requestfrom urllib.parse import quoteimport stringimport requests
# 静态页面基类class StaticBase():    # 获取网页内容   使用的requests 库实现 def __getHTMLText(self,url,code="utf-8"): try: r = requests.get(url) r.raise_for_status() r.encoding = code return r.text except: return ""    # get方式请求数据  通过urllib记性实现GET请求 def getUrl(self,url,code='utf-8'): url = quote(url,safe=string.printable) req = request.Request(url) req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36') with request.urlopen(req) as f: print('Status:',f.status,f.reason) return f.read().decode(code)
#s = StaticBase()#print(s.getUrl('http://www.baidu.com/','utf-8'))

- 配置文件

{   "host": "http://shangyu.108sq.cn",    "base_url""http://shangyu.108sq.cn/shuo/search?sertype=4"   "key_words""污染"   "page_size"30   "search_key"""   "last_request_time"1562142204.149511   "request_gap"60  } 

- 解析服务

#!/usr/bin/env python # -*- coding:utf-8 -*-from bs4 import BeautifulSoupfrom datetime import datetimeimport jsonfrom common.staticBase import StaticBase
class Shangyh108(StaticBase):
__config_file = "config.json" #配置文件 __text = "" #解析的网页内容 __config_dict = {} #配置集合 __url = "" #请求的URL __keywords = "" #关键字 __last_request_time = 0 #上次请求时间 # 构造函数 def __init__(self): self.__config_dict = self.__getConfig() # 查询关键字 if len(self.__config_dict['search_key']) >0 : self.__keywords = self.__config_dict['search_key'] else: self.__keywords = self.__config_dict['key_words'] self.__url = self.__getUrl() # 获取网页内容 def getText(self): print(self.__url) self.__text = StaticBase.getUrl(self,self.__url)
# 获取第一页内容 def getFirstPageText(self,url=''): if self.checkRquestTime(): if len(url)==0 : url = self.__getUrl() self.__text = StaticBase.getUrl(self,url) return self.parseHTML() else: print("操作频繁请稍后重新") # 获取下一页 def getNextPage(self,url): url = self.__config_dict['host']+url print(url) self.__text = StaticBase.getUrl(self,url) return self.parseHTML()
# 为防止请求对服务器造成太大压力,控制请求的时间间隔,最少为5分钟 def checkRquestTime(self): request_gap = self.__config_dict['request_gap'] last_request_time = self.__config_dict['last_request_time'] dt_now = datetime.now().timestamp() self.__last_request_time = last_request_time # 记录上次请求的时间,为了获取阶段性的数据 if last_request_time == 0: #第一次请求,直接通过 last_request_time = dt_now elif last_request_time+request_gap > dt_now: print("请求过度频繁,请稍后重试") return False else: last_request_time = dt_now
self.__setConfig('last_request_time',last_request_time) return True
# 获取网页描述信息 def getDesc(self): self.getText() soup = BeautifulSoup(self.__text,'html.parser') obj_count = soup.select('.count')[0] count_str = str(obj_count.string).replace("(共","").replace("条)","") count = int(count_str) pageSize = int(self.__config_dict['page_size']) host = self.__config_dict['host'] if count % pageSize == 0 : pages = count//pageSize else: pages = count // pageSize + 1 desc = {} desc['host'] = host desc['count'] = count desc['page_size'] = pageSize desc['total_page'] = pages # 增加分页的URL if pages > 0 : pageUrls = soup.select(".TCPage__middle > a") page_url = [] for i in range(len(pageUrls)-1) : tag = pageUrls[i+1] page_url.append(tag['href']) desc['page_url'] = page_url return json.dumps(desc,ensure_ascii=False)
# 解析网页内容 def parseHTML(self): soup = BeautifulSoup(self.__text, 'html.parser') list_li = soup.select('.TCSayList .TCSayList_li') data_list = [] for i in range(len(list_li)): item = {} temp = list_li[i] publish_time = temp.select('.TCSayList_li_time')[0] int_dt = int(publish_time['data-time'])
if self.__last_request_time == 0 or self.__last_request_time < int_dt : # 发布时间 item['publish_time_long'] = publish_time['data-time'] item['publish_time_str'] = datetime.fromtimestamp(int(publish_time['data-time'])).strftime( '%Y-%m-%d %H:%M:%S')
# 数据标签 item['data-tag'] = temp['data-tag'] # 用户 author = temp.select('.TCSayList_li_author')[0] item['author_name'] = author.string item['author_url'] = author['href']
# 标题 if len(temp.select('.TCSayList__title a')) >0: title = temp.select('.TCSayList__title a')[0] item['title'] = title.string item['link_url'] = title['href'] # 内容 item['content'] = temp.select('.TCSayList_li_content')[0]['data-short']
data_list.append(item) return data_list # 获取请求配置信息 def __getConfig(self): with open(self.__config_file, "r",encoding="utf-8") as load_f: load_dict = json.load(load_f) return load_dict # 设置配置项 def __setConfig(self,key,value): self.__config_dict[key] = value print(self.__config_dict) with open(self.__config_file,'w',encoding="utf-8") as f: f.write(json.dumps(self.__config_dict,ensure_ascii=False))
def getKeywords(self): self.__keywords = input("请输入查询的关键字,多个关键字用“+”连接,默认关键字:环保+污染+投诉,使用默认关键字可直接按Enter:") if len(self.__keywords) == 0: self.__keywords = self.__config_dict['key_words'] else: self.__setConfig("search_key",self.__keywords)
# 获取请求的URL def __getUrl(self): base_url = self.__config_dict['base_url'] # 组装查询参数 url = base_url + "&key=" + self.__keywords return url

- REST服务端(目前服务没有暴露很多,但相应服务实现都已经实现)

#!/usr/bin/env python # -*- coding:utf-8 -*-from flask import Flask,jsonify,abort,requestfrom changshuo108.shangyu.Shangyh108 import Shangyh108
app = Flask(__name__)# 支持中文app.config['JSON_AS_ASCII'] = Falseshangyue = Shangyh108()@app.route('/shangyu108/api/desc',methods=['GET'])def get_desc(): return shangyue.getDesc()
@app.route('/shangyu108/api/first_page',methods=['GET'])def get_firstPage(): return jsonify({'data':shangyue.getFirstPageText('')})
@app.route('/shangyu108/api/page',methods=['POST'])def get_article(): if not request.json or not 'url' in request.json: abort(400) print(request.json['url']) return jsonify({'data':shangyue.getNextPage(request.json['url'])})
if __name__ == '__main__': app.run(debug=True)
公众号链接:https://mp.weixin.qq.com/s?__biz=Mzg4MzI3MjM4NQ==&tempkey=MTAxNl9KVjVnVCtVNlo4RUpIZmZXbzBfSVR4dHU4YUhhX3hPNGMxVXdMd1JaQ21OZExlNnNybmJzaVhCT2hkZk85RzZKbzRlYWxFcEk1U2g5bmN4cWJ1QlNmNEdmWlBvVWxGTER2NDM5NjdWa1VIaDVWZlFyUF9EVmtYM0lmNnplRzRjanZsWEo4RUlESTg2YlFkVjBxdDFXbzEwR1UtVVpSd2V5U0R1YUVnfn4%3D&chksm=4f48bebe783f37a8622096cf8cb7d5dfbc5d913e3f1694ea601f51eec5aadddee66271739639#rd

转载于:https://www.cnblogs.com/xiaotao726/p/11141833.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python爬虫是一种自动化程序,可以通过requests和beautifulsoup等库来获取网页信息,并使用pandas等工具对数据进行处理和分析。使用Python爬虫可以快速获取大量数据,帮助我们进行数据挖掘和分析。 ### 回答2: Python是一种强大的编程语言,在网络爬虫方面也有着广泛应用。requests、BeautifulSoup和Pandas就是其中的三个非常重要的工具,它们各自的功能和作用如下: Requests(请求):是一个Python中的HTTP库,可以轻松的发送HTTP请求,并且可以很容易地获取返回的内容。如果你想获取一个网页的HTML代码,你可以使用Requests库。你需要向requests.get()方法传递一个URL,然后它会返回一个response对象,可以通过response.text来获取文本内容。 BeautifulSoup(漂亮的汤):是Python一个解析HTML和XML文件的库,它可以从这些文件中提取有用的信息。所以,你可以使用BeautifulSoup来提取网页中的信息。通过BeautifulSoup库可以把一个已经读入python中的response响应文件对象进行分析,也就是通过一些HTML标签(soup.a/b/p/div),来获取我们想要的内容。 Pandas(熊猫):是一个强大的数据分析工具,其核心是用于数据处理和矩阵计算的高效核心数据结构Dataframe。使用Pandas库可以很容易地从文本文件中导入数据,然后进行数据清洗、规整、合并、并统计数据等等各类操作。下面我们详细介绍一下这些库的用法。 在进行数据抓取之前,我们首先需要对需要抓取的数据进行需求分析,即确定需要抓取的网站、需要抓取的数据点和格式,以及需要进行的数据处理方式和数据储存方式等。当我们完成了需求分析之后,就可以开始进行数据抓取了。 首先我们需要安装requests、BeautifulSoup和Pandas库: ```python pip install requests pip install BeautifulSoup4 pip install pandas ``` 然后我们可以使用以下代码,来展示如何进行数据抓取: ```python import requests from bs4 import BeautifulSoup import pandas as pd # 请求URL并将结果解析为HTML url = 'https://movie.douban.com/top250' resp = requests.get(url) html_data = resp.text soup = BeautifulSoup(html_data, 'html.parser') # 获取电影名称和评分信息 movie_list = soup.find_all('div', class_='hd') title_list = [movie.a.span.text for movie in movie_list] rating_list = [movie.find_next_siblings('div')[0].span.text for movie in movie_list] # 构建DataFrame并将结果保存为CSV文件 movie_df = pd.DataFrame({'title': title_list, 'rating': rating_list}) movie_df.to_csv('top250_movies.csv', index=False) ``` 通过以上代码,我们可以获取到豆瓣电影Top250的电影名称和评分信息,并将结果储存为CSV文件。 总之,requests、BeautifulSoup和Pandas是Python网络爬虫中非常常用的工具。使用这些库,我们可以轻松地进行数据抓取、数据提取、数据处理和数据储存等操作。同时,我们在进行爬虫之前,一定要注意合法性和尊重原网站的规则。 ### 回答3: Python是目前最流行的编程语言之一,其生态系统非常丰富,可以应用于各种领域。其中,爬虫Python应用广泛的领域之一。在Python爬虫中,requests、beautifulsoup和pandas都是非常常用的库。 requests是一个用于HTTP请求的Python库,可以方便地发送网络请求,并且可以处理响应数据。在Python爬虫中,我们通常使用requests库下载网页内容。例如,我们可以使用requests库的get方法获取网页内容,如下所示: ``` import requests response = requests.get('http://www.baidu.com') print(response.text) ``` beautifulsoup是一个解析HTML和XML文档的Python库,可以方便地从网页中提取所需的数据。使用beautifulsoup库,我们可以方便地解析从网页中提取的数据,并进行数据清洗和处理。例如,我们可以使用beautifulsoup库的find_all方法查找特定标签中的文本内容,如下所示: ``` from bs4 import BeautifulSoup import requests response = requests.get('http://www.baidu.com') soup = BeautifulSoup(response.text, 'html.parser') print(soup.find_all('a')) ``` pandas是一个用于数据分析和处理的Python库,提供了许多有用的功能,例如读取、处理和分析数据。在Python爬虫中,我们通常使用pandas库来处理从网页中提取的数据,并将其保存到CSV文件或数据库中以供进一步分析。例如,我们可以使用pandas库的read_html方法读取HTML表格数据,并将其保存为CSV文件,如下所示: ``` import pandas as pd url = 'http://www.example.com' tables = pd.read_html(url) df = tables[0] df.to_csv('example.csv', index=False) ``` 综上所述,Python爬虫中的requests、beautifulsoup和pandas库是非常重要的工具,能够帮助我们方便地下载网页内容、提取数据和进行数据处理和分析。如果您有兴趣学习Python爬虫,那么这些库将是您必须掌握的重要工具之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值