美文网首页
2020-07-16

2020-07-16

作者: 杜宇_8141 | 来源:发表于2020-07-17 15:09 被阅读0次

    爬虫学习一

    我的系统环境是ubuntu20.04,使用python3.8。

    1.了解网页结构

    • 打开chrome浏览器,按F12进入开发者模式,点击左上角箭头,再点击网页内容会找到源代码对应位置。

    • 点击Network,会看到浏览器向服务器发出的请求时间图,点击图中最左边,再点击Headers,General包含url、远程服务器ip地址等信息,Response Headers是对服务器响应的格式约束,Request Headers包含了我们的浏览器信息。点击Response,看到服务器返回的信息。

    2.爬虫框架

    2.1整体框架

    以爬取豆瓣top250影片信息为例

     # -*- coding:utf-8 -*-
    import urllib.request as ur
    from bs4 import BeautifulSoup#网页解析获取数据
    import re#正则表达式,进行文字匹配
    import urllib.request,urllib.error#制定URL,获取数据
    import xlwt#用于保存成excel
    import sqlite3#进行SQLite数据库操作
    def main() :
        baseurl = "https://movie.douban.com/top250?start="
        datalist = getData(baseurl)
        savepath = "./Top250.xls"
        saveData(datalist,savepath)
        
    
    findLink = re.compile(r'<a href="(.*?)">')
    #影片图片的规则
    findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S)#re.S让换行符包含在字符中
    #影片片名
    findTitle = re.compile(r'<span class="title">(.*)</span>')
    #影片评分
    findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
    #评价人数
    findJudge = re.compile(r'<span>(\d*)人评价</span>')
    #找到概况
    findInq = re.compile(r'<span class="inq">(.*)</span>')
    #找到影片的相关内容
    findBd = re.compile(r'<p class="">(.*?)</p>',re.S)
    def getData(baseurl) :
        datalist = []
        for i in range(0,10) :
            url = baseurl + str(i*25)
            html = askURL(url)
            soup = BeautifulSoup(html,"html.parser")
            for item in soup.find_all('div',class_='item') :
                data = []
                item = str(item)
                link = re.findall(findLink,item)[0]
                data.append(link)
                imgSrc = re.findall(findImgSrc,item)[0]
                data.append(imgSrc)
                titles = re.findall(findTitle,item)
                if (len(titles) == 2) :
                    ctitle = titles[0]
                    data.append(ctitle)
                    otitle = titles[1].replace('/','')
                    data.append(otitle)
                else :
                    data.append(titles[0])
                    data.append(' ')
                rating = re.findall(findRating,item)[0]
                data.append(rating)
                judgeNum = re.findall(findJudge,item)[0]
                data.append(judgeNum)
                inq = re.findall(findInq,item)
                if len(inq) != 0 :
                    inq = inq[0].replace("。",'')
                    data.append(inq)
                else :
                    data.append(" ")
                bd = re.findall(findBd,item)[0]
                bd = re.sub('<br(\s+)?'," ",bd)
                bd = re.sub('/'," ",bd)
                data.append(bd.strip())
                datalist.append(data)
        print(len(datalist))    
        return datalist
    
    def askURL(url) :
        headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}#构建一个header,防止被发现是爬虫,User-Agent不要出现空格
        request = ur.Request(url=url,headers=headers)#构建一个请求
        response = ur.urlopen(request)#发送请求
        try :
            response = ur.urlopen(request)
            html = response.read().decode("utf-8")
        #    print(html)
            return html
        except urllib.error.URLError as e :
            if hasattr(e,"code") :
                print(e.code)
            if hasattr(e,'reason') :
                print(e.reason)
    
    def saveData(datalist,savepath) :
        book = xlwt.Workbook(encoding = "utf-8",style_compression=0) #创建workbook对象
        sheet = book.add_sheet('doubanTop250',cell_overwrite_ok=True)#创建工作表
        col = ('电影详情链接','图片链接','影片中文名','影片外文名','评分','评价数','概况','相关信息')
        for i in range(0,8) :
            sheet.write(0,i,col[i])
        for i in range(0,250) :
            print("第%d条"%(i+1))
            data = datalist[i]
            for j in range(0,8) :
                sheet.write(i+1,j,data[j])
        book.save(savepath)
    #影片详情链接的规则
    
    
    if __name__ == "__main__" :
        main()                                                                                                                                                                                      
    

    2.2抓取网页源代码

    有的写法是import urllib,然后urllib.request.Request,但是这样会显示urllib没有request模块,应该是由于python版本的问题。User-Agent在浏览器的Request Headers中可以找到。

    def askURL(url) :
        headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}#构建一个header,防止被发现是爬虫,User-Agent不要出现空格
        request = ur.Request(url=url,headers=headers)#构建一个请求
        response = ur.urlopen(request)#发送请求
        try :
            response = ur.urlopen(request)
            html = response.read().decode("utf-8")
            print(html)
            return html
           
        except urllib.error.URLError as e : 
            if hasattr(e,"code") :
                print(e.code)
            if hasattr(e,'reason') :
                print(e.reason)
    
    

    给askURL函数传入百度首页的URL:https://www.baidu.com,就会打印出百度首页的源代码,内容较多,这里就不展示了。注意,如果返回错误信息418,则说明对方服务器识别出爬虫。
    将打印内容保存到baidu.html中,用chrome浏览器打开,会发现正是百度首页的界面

    baidu.html

    2.3网页解析

    对于一个保存好的网页baidu.html,我们可以通过BeautifulSoup来进行解析

    from bs4 import BeautifulSoup
    file = open("./baidu.html","rb")
    html = file.read()
    bs = BeautifulSoup(html,"html.parser")
    #print(bs.title)
    #print(bs.a)
    #print(bs.head)
    #查找含标签"a"的分区
    t_list = bs.find_all("a")
    print(t_list) 
    #函数法
    def name_is_exists(tag) :
      return tag.has_attr("name")
    t_list = bs.find_all(name_is_exists)
    print(t_list)
    #Kwargs参数,注意class_有下划线
    #t_list = bs.find_all(id = "head")
    t_list = bs.find_all(class_=True)
    for item in t_list :
      print(item)
    #text参数
    t_list = bs.find_all(text = "hao123")
    t_list = bs.find_all(text = ["hao123","地图",“贴吧”])
    for item in t_list :
      print(item)
    #limit参数,限制最多查找个数
    t_list = bs.find_all("a",limit=3)
    for item in t_list :
      print(item)
    #CSS选择器
    #t_list = bs.select('title') #通过标签来查找
    #t_list = bs.select(".mnav") #通过类名来查找
    #t_list = bs.select("#v1")#通过id来查找
    #t_list = bs.select("a[class='bri'])#通过属性查找
    #t_list = bs.select("head > title")#通过子标签
    t_list = bs.select(".mnav ~ .bri")#通过兄弟标签
    print(t_list[0].get_text())
    
    

    2.4正则表达式提取信息

    正则表达式能够精确提取信息,这里直接搬运一下常用操作符


    常用操作符1 常用操作符2
    举例,如何匹配aabbcc@126.com,可以用.*@126.com
    Re库主要功能函数
    修饰符
    举例
    import re
    #创建模式对象
    pat = re.compile("AA")
    m = pat.search("ABCAADDCCAAA")
    print(m)#默认返回第一个匹配到的位置
    #输出结果<re.Match object; span=(3, 5), match='AA'>
    #无模式对象匹配
    #m = re.search("asd","Aasd")
    #print(m)
    print(re.findall("a","ASDaDFGAa"))
    print(re.findall("[A-Z]+","ASDaDFGAa"))
    #替换方法sub
    print re.sub("a","A","abcdcasd"))
    #找到所有'a',并将其替换为'A'
    

    建议在正则表达式中,被比较的字符串前面加上r,如 r"\aabd-'",不用担心转义字符的问题。

    2.5保存数据

    def saveData(datalist,savepath) :
        book = xlwt.Workbook(encoding = "utf-8",style_compression=0) #创建workbook对象
        sheet = book.add_sheet('doubanTop250',cell_overwrite_ok=True)#创建工作表
        col = ('电影详情链接','图片链接','影片中文名','影片外文名','评分','评价数','概况','相关信息')
        for i in range(0,8) :
            sheet.write(0,i,col[i])
        for i in range(0,250) :
            print("第%d条"%(i+1))
            data = datalist[i]
            for j in range(0,8) :
                sheet.write(i+1,j,data[j])
        book.save(savepath)
    
    

    最终得到这样一张excel表


    保存结果

    3.补充

    3.1 get和post方法的区别

    get请求:
    一般情况下,只从服务器获取数据,并不会对服务器数据产生影响的时候用get请求;
    如 :

    response = urllib.request.urlopen("http://httpbin.org/get")
    print(response.read().decode("utf-8"))
    

    post请求:
    向服务器发送数据(登录),上传文件等,会对服务器资源产生影响的时候用post请求

    import urllib.parse
    data = bytes(urllib.parse.urlencode({"hello":"world"}),encoding="utf-8")
    response = urllib.request.urlopen("http://httpbin.org/post",data=data)
    print(response.read().decode("utf-8"))
    

    相关文章

      网友评论

          本文标题:2020-07-16

          本文链接:https://www.haomeiwen.com/subject/vdhphktx.html