python爬虫的原理

先上代码再解释:

# 事先声明,运行环境:win10,pycharm+python3.5,Any question will be valued!

# 代码是根据这个修改的原来是python2,http://www.maiziedu.com/wiki/crawler/example/,为了进行一步理解python爬虫的原理,这个基础只之上进一步做出了修改,下面的url可以换成任意的网页,但是编码可能出现问题,


import urllib
import urllib.request
#from html.parser import HTMLParser
from html.parser import HTMLParser
#print(dir(HTMLParser))
import re
import requests

import time
#print(dir(urllib.request.urlopen.__dict__))

class MovieParser(HTMLParser): #定义电影解析器
    
    def __init__(self):
        HTMLParser.__init__(self) #调用父类的构造函数
        self.movies = [] #定义一个数组来保存电影,默认为空
    
    def handle_starttag(self,tag,attrs): #重载这个方法,去解析li这个数据
        # tag 是标签  attrs是属性列表[(属性,对应属性的值),...],元组的列表

        #print("Done!'\n")
        #print(tag,attrs)
        print(" tag : {0}    | attrs :   {1}\n".format(tag,attrs))
        def _attr(attrlist,attrname):#定义一个函数来解析属性
            #time.sleep(10)
            for attr in attrlist:
                #print(attr,attr[0],attrname)
                if attr[0] == attrname: #如果这个属性名称和要求的一样
                    #print(attr[1])
                    return attr[1] #返回属性的值
            return None #如果没有找到返回空
        if len(attrs)>0:
            #print(" tag : {0}    |attrs :   {1}\n".format(tag, attrs))
            if tag == 'li' and _attr(attrs,'data-title') is not None:
                #print(attrs)
                movie = {}
                movie['title'] = _attr(attrs,'data-title') #电影名称
                movie['score'] = _attr(attrs,'data-score') #电影分数
                movie['director'] = _attr(attrs,'data-director') #电影导演
                movie['actors'] = _attr(attrs,'data-actors') # 电影演员
                self.movies.append(movie) #提取出的电影放到列表里面
                #print('%(title)s|%(score)s|%(director)s|%(actors)s' % movie)
                print('%(title)s|%(score)s|%(director)s|%(actors)s' % movie)
            
        
        
        
        
def nowplaying_movies(url):
    #headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36'}   # 
    headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.119 Safari/537.36'}
    #请求头
    #模拟一个浏览器的行为
    #req = urllib.request(url, headers=headers)  #定制一个http头
    print(url)
    #s = urllib.request.urlopen(url)  #获取这个请求
    s = requests.get(url,headers=headers)
    s.encoding = 'utf-8' #防止发生编码错误
    #print(s.read()) #  读取得是字节类型,必须进行解码
    parser = MovieParser() #解析器
    #print(s.content.decode('utf-8'))  #解码之后得到整个h网页得代码,里面有我们需要得内容
    # 使用utf-8进行解码
    parser.feed(s.content.decode())

    #s.close()
    return parser.movies  #把解析器里面的movies返回给调用者
    
if __name__ == '__main__':
    
    #url = 'http://movie.douban.com/nowplaying/xiamen/' #豆瓣热播电影的地址,还有分城市
    url = 'http://www.maiziedu.com/wiki/crawler/multi/'
    movies = nowplaying_movies(url)  #定义一个函数nowplaying_movies,就是当前正在热播的电影,我们希望这个函数传进去就是url,还会就是一个电影列表

import json

#json 默认使用ASCII编码,所以不显示汉字
print('%s' % json.dumps(movies, ensure_ascii=False,sort_keys=True, indent=4, separators=(',', ': ')))  # 这个电影列表通过 json把它编码一下,打印出来
          
<!DOCTYPE html>
<html lang="zh-cmn-Hans" class="ua-windows ua-webkit">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="renderer" content="webkit">
    <meta name="referrer" content="always">
    <meta name="google-site-verification" content="ok0wCgT20tBBgo9_zat2iAcimtN4Ftf5ccsh092Xeyw" />
    <title>
    厦门 - 在线购票&amp;影讯
</title>
    
    <meta name="baidu-site-verification" content="cZdR4xxR7RxmM4zE" />
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="Sun, 6 Mar 2005 01:00:00 GMT">
    
    
    <meta name="keywords" content="厦门,在线购票,网上电影票预订,优惠电影票,影讯,排片,放映时间,电影票价"/>
    <meta name="description" content="厦门电影院在线优惠购票及影讯排片查询"/>

    <link rel="apple-touch-icon" href="/pics/movie/apple-touch-icon.png">
    <link href="https://img3.doubanio.com/f/shire/52c9997d6d42db58eab418e976a14d5f3eff981e/css/douban.css" rel="stylesheet" type="text/css">
    <link href="https://img3.doubanio.com/f/shire/ae3f5a3e3085968370b1fc63afcecb22d3284848/css/separation/_all.css" rel="stylesheet" type="text/css">
    <link href="https://img3.doubanio.com/f/epstein/85f16e2319c370ecd16bbca53d5d006adaa99728/css/movie/base/init.css" rel="stylesheet" type="text/css">
    <script type="text/javascript">var _head_start = new Date();</script>
    <script type="text/javascript" src="https://img3.doubanio.com/f/epstein/0495cb173e298c28593766009c7b0a953246c5b5/js/movie/lib/jquery.js"></script>
    <script type="text/javascript" src="https://img3.doubanio.com/f/shire/1316664523258f7b8b536e4ce45afc9cb37b8963/js/douban.js"></script>
    <script type="text/javascript" src="https://img3.doubanio.com/f/shire/0efdc63b77f895eaf85281fb0e44d435c6239a3f/js/separation/_all.js"></script>

上面是打印出的原始网页(由于网页太长),可在任意浏览器中打开检查元素就可以进行对比是不是原始网页,我们所有需要的东西都在上面的网页里面,其实上面的html代码关键就是标签tag,和标签对应的属性名attrname,以及属性的值attrvalue,这3个东西,这也是我们爬虫的关键的3个部分,我们爬虫其实就是根据tag,attrname,attrvalue进行逐层的查找匹配(正则表达式),首先我们要在网页源码中找到我们需要的东西(一般都是attrvalue),然后看这个attrname在哪个attrname下面包含着,最后找到包含这个attrname的tag。

 

那么我们如何得到网页的tag,和attrname,attrvalue呢,我们可以通过重写HTMLParser的handle_starttag方法,通过这个方法可以得到每个tag(str),和其对应的tuple= (attrname,attrvalue)的列表(list),这样就可以通过遍历进行匹配了。下面我们打印出来就一目了然了。

 tag : li    | attrs :   [('id', '26794435'), ('class', 'list-item hidden'), ('data-title', '哪吒之魔童降世'), ('data-score', '8.6'), ('data-star', '45'), ('data-release', '2019'), ('data-duration', '110分钟'), ('data-region', '中国大陆'), ('data-director', '饺子'), ('data-actors', '吕艳婷 / 囧森瑟夫 / 瀚墨'), ('data-category', 'nowplaying'), ('data-enough', 'True'), ('data-showed', 'True'), ('data-votecount', '943503'), ('data-subject', '26794435')]

哪吒之魔童降世|8.6|饺子|吕艳婷 / 囧森瑟夫 / 瀚墨
 tag : ul    | attrs :   [('class', '')]

 tag : li    | attrs :   [('class', 'poster')]

 tag : a    | attrs :   [('href', 'https://movie.douban.com/subject/26794435/?from=playing_poster'), ('class', 'ticket-btn'), ('target', '_blank'), ('data-psource', 'poster')]

 tag : img    | attrs :   [('src', 'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2563780504.jpg'), ('alt', '哪吒之魔童降世'), ('rel', 'nofollow'), ('class', '')]

 tag : li    | attrs :   [('class', 'stitle')]

 tag : a    | attrs :   [('href', 'https://movie.douban.com/subject/26794435/?from=playing_poster'), ('class', 'ticket-btn'), ('target', '_blank'), ('title', '哪吒之魔童降世'), ('data-psource', 'title')]
[
    {
        "actors": "唐国强 / 刘劲 / 黄景瑜",
        "director": "黄建新 宁海强",
        "score": "7.0",
        "title": "决胜时刻"
    },
    {
        "actors": "黄渤 / 张译 / 吴京",
        "director": "陈凯歌 张一白 管虎 薛晓路 徐峥 宁浩 文牧野",
        "score": "0",
        "title": "我和我的祖国"
    },
    {
        "actors": "平采娜·乐维瑟派布恩 / 奈哈·西贡索邦 / 杰森·杨",
        "director": "查亚诺普·布恩帕拉科布",
        "score": "6.6",
        "title": "友情以上"
    },
    {
        "actors": "山新 / 郝祥海 / 刘明月",
        "director": "木头",
        "score": "8.2",
        "title": "罗小黑战记"
    },
    {
        "actors": "吴京 / 章子怡 / 张译",
        "director": "李仁港",
        "score": "0",
        "title": "攀登者"
    },
    {
        "actors": "肖战 / 李沁 / 孟美岐",
        "director": "程小东",
        "score": "5.3",
        "title": "诛仙 Ⅰ"
    },
    {
        "actors": "任达华 / 梁咏琪 / 罗仲谦",
        "director": "罗永昌",
        "score": "6.9",
        "title": "小Q"
    },

python异步爬虫-下拉网页爬取

以知乎问答为例,对于其他的网页比如今日头条和淘宝美团点评也类似,

 打开https://www.zhihu.com/question/21400402,打开浏览器检查->网络->XHR

 

首先找到这个问题下第一个回答对应的url连接,见上图第一个空色方框,由于一个网页可以容纳的回答有限,这里总共有225个回答,鼠标往下滚动刷新,发现最左边的内容变多了,我们通过第一个url只能获取5个回答,那么如何获取所有的回答呢,如果我们能发现所有url的规律不是可以了?

通过分析表头的url参数可知不同的回答有个offset参数不一样其他都是一样的,直接循环一下就好了,当然由于不同的前段方法有些参数也可以是page或者其他

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值