美文网首页Python 爬虫专栏@IT·互联网Python爬虫作业
python爬虫——知乎(关于python的精华回答)

python爬虫——知乎(关于python的精华回答)

作者: loading_miracle | 来源:发表于2017-05-02 21:29 被阅读1006次

    <strong>之前的文章都是与职位、热门文章有关的,今天一起来看一下知乎上与python相关的精华回答(主要是requests,scrapy处理的思路,编码问题)</strong>

    知乎python精华回答

    1.采集的信息

    <ol>
    <li>问题题目</li><li>问题对应URL</li><li>回答的作者</li><li>作者主页URL</li><li>回答获赞数</li><li>回答详情URL</li></ol><strong>主要获取以上信息,接着我们来看一下这些字段所在的位置

    字段位置

    通过观察和分析以上字段在源码中都能找到,所以就不用像前几篇文章那样,构造参数,解析获取返回的json数据,我们可以通过lxml.etree.HTML()或者Beautifulsoup去解析(这里在通过etree解析时遇到了一些问题,在后边会进行解释)
    既然不需要通过构造参数去获取数据了,所以相对来说就简单一些了,接下来我们来看一下另一个很重要的问题——分页问题</strong>

    第一页 第二页

    <em>从上面两张图片我们可以看出换页之后参数<strong>page</strong>发生了改变,很显然<strong>page</strong>控制的是页码,明白了这一点就可以去构造URL了</em>

    2.构造URL

    总页数
    urls = ['https://www.zhihu.com/topic/19552832/top-answers?page={}'.format(one) for one in range(1,51)]
    

    <strong>解决了分页问题,就没什么难点了,接下来说一下遇到的问题和解决方法

    • 通过Beautifulsoup解析页面
    # -*- coding:utf-8 -*-
    import requests
    from bs4 import BeautifulSoup
    from store_csv import CSV
    from store_mysql import Mysql
    class zhiHu(object):
        baseurl = 'https://www.zhihu.com'
        headers = {
            "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
        }
        cookies = {
            'd_c0': '"AHACIj6lFguPTkEZTVmz8MPJ8UkcuI03hag=|1483278273"',
            '_zap': '108369f2-93e6-407e-8928-b57f44168838',
            'q_c1': '0d3d690c67bc4b12a163beb462e17d67|1492571575000|1483278273000',
            'cap_id': '"NmFlNDgyZmMxNWQ0NGFiYmFhZThmMGM2MDVkZDM1MWM=|1493684435|1958b2bb9fb6f09116056cc4bc5af76e00dbaff7"',
            'l_cap_id': '"ZjViYmQ0MzBkNTFjNGJjOWE5YTExZWRjMjlkNjM2YjQ=|1493684435|1204e5c054805d8bebf3b49a8a2fc09e2f1bd870"',
            'auth_type': '"c2luYQ==|1493684515|245a0f575f151c486829c687ba3d3c90fc5fa558"',
            'token': '"Mi4wMGljWjNYRkVBNzIyRGJjZDZkMjMyZmMwM2JtMWs=|1493684515|a76491c048b7e825a77983ef0a272bdc9e721853"',
            'client_i': '"NTA3MzY2MzQwNA==|1493684515|9a08a2c9a6c02e86da4810cb5bc4437f6d7b1028"',
            'aliyungf_tc': 'AQAAAFOsE04F5QQAHVcc2i2qHTGdX1x0',
            'acw_tc': 'AQAAAAnnBnQS0AcAHVcc2omDblHld+wt',
            '_xsrf': '398e0b041f39355dadfc06b76ba18cdb',
            's-q': 'python',
            's-i': '1',
            'sid': 'ob2ttqkg',
            's-t': 'autocomplete',
            'z_c0': 'Mi4wQUFBQ3hmbTFzUXNBY0FJaVBxVVdDeGNBQUFCaEFsVk5OVjR2V1FETW9QS19PRlExWGVjUHNOcFVoTG5mYWg1LUtR|1493701061|4258e8f2ddc800c42c8b7d94385f578ca97f34d5',
            '__utma': '51854390.213172690.1484833633.1493684449.1493701029.4',
            '__utmb': '51854390.0.10.1493701029',
            '__utmc': '51854390',
            '__utmz': '51854390.1493701029.4.4.utmcsr=baidu|utmccn=(organic)|utmcmd=organic',
            '__utmv': '51854390.100--|2=registration_date=20170502=1^3=entry_date=20170101=1'
        }
        def getUrl(self):
            urls = ['https://www.zhihu.com/topic/19552832/top-answers?page={}'.format(one) for one in range(1,51)]
            for url in urls:
                self.getData(url)
        def getData(self,url):
            data = requests.get(url, headers=self.headers, cookies=self.cookies).content.encode('utf-8')
            soup = BeautifulSoup(data, 'lxml')
            infos = soup.find_all('div', {'class': 'feed-item feed-item-hook folding'})
            item = {}
            for info in infos:
                item[1] = info.find('a',{'class':'question_link'}).get_text().strip()
                item[1] = item[1].replace("'","=")
                item[2] = self.baseurl+info.find('a',{'class':'question_link'}).get('href')
                try:
                    item[3] = info.find('a',{'class':'author-link'}).get_text()
                except:
                    item[3] = u'匿名用户'
                try:
                    item[4] = self.baseurl+info.find('a',{'class':'author-link'}).get('href')
                except:
                    item[4] = u''
                item[5] = info.find('a',{'class':'zm-item-vote-count js-expand js-vote-count'}).get_text()
                try:
                    item[6] = self.baseurl+info.find('a',{'class':'toggle-expand'}).get('href')
                except:
                    item[6] = u''
                self.store(item)
        def store(self,item={}):
            #row = [item[i] for i in range(1,7)]
            #wirte.writeRow(row)
            mysql.insert(item)
    if __name__ == "__main__":
        #firstRow = ['问题', '问题URL', '回答者', '回答者URL', '获赞', '详细信息URL']
        #wirte = CSV('zhihu.csv',firstRow)
        row = ['question','qurl','autuor','aurl','zan','detail']
        mysql = Mysql('zhihu',row,7)
        mysql.create_table()
        zhihu = zhiHu()
        zhihu.getUrl()
    

    </strong><em>这里说明一点,from store_csv import CSV,from store_mysql import Mysql这两个是自己写的两个类,实现方法可以参考python简单操作csv文件小例和老哥Mr_Cxypython对Mysql数据库的操作小例这两篇文章,这里可以不添加cookie信息</em>
    <strong>

    • 通过etree解析页面(和之前一样都是找到循环点,然后取值,这里主要说一下遇到的问题和解决的方法)
    • 问题</strong>
      html = requests.get(url,headers=headers)
      这里有不同方式,一种是html.content,另一种是html.text之前没遇到出错的情况(通过content出现了编码问题,python版本2.7),今天遇到了就记录一下:
      resp.text返回的是Unicode型的数据。
      resp.content返回的是bytes型也就是二进制的数据。
      也就是说,如果你想取文本,可以通过r.text。
      如果想取图片,文件,则可以通过r.content。
    • <strong>方法</strong>
      主要说一下html.content的解决方案
    selector = etree.HTML(html.content.decode('utf-8'))
    

    通过对html.content进行解码,输出结果正常。

    3.scrapy版本思路

    • <strong>1.使用start_requests()重写初始URL控制或者在parse函数中进行分页的控制
    yield scrapy.Request(url,callback=self.parse)
    

    </strong><em>代码中提到的URL指的是下一页的URL,通过获取下一页信息调用parse函数抓取信息</em><strong>

    下一页
    • 2.之前通过观察URL,我们发现只有page之后的数字发生了变化,所以我们可以使用爬取规则CrawlSpider去获取不同页面的信息(给一个之前抓取智联招聘职位详情页面的规则作为参考)
          # -*- coding: utf-8 -*-
          from scrapy.spider import CrawlSpider,Rule
          from scrapy.linkextractors import LinkExtractor
          from ..items import ZlzpItem
      
          class ZLZP_Spider(CrawlSpider):
              name = 'ZLZP'
              start_urls = [
                  'http://jobs.zhaopin.com/'
              ]
              rules = [
              Rule(LinkExtractor(allow=('http://jobs.zhaopin.com/[a-zA-Z0-9]*\.htm',)), follow=True,
                 callback='parse_item')]
              def parse_item(self, response):
      

    这里使用了parse_item进行页面数据的提取(编写爬虫规则时,避免使用 parse 作为回调函数。 由于 CrawlSpider
    使用 parse方法来实现其逻辑,如果覆盖了 parse方法,crawl spider 将会运行失败。)
    关于CrawlSpider
    的详细使用方法可以参考官方文档或者参考相关的代码和文章

    4.数据信息(mysql和csv)

    mysql zhihu.csv

    总结

    通过对比动态网页(ajax)和静态网页,在思想上差别不是很大(参数+分页),在解析方式动态的一般都是通过解析json来获取数据,静态则通过Beautifulsoup、xpath、正则去获取数据。
    爬爬爬,下一个网站走起!

    相关文章

      网友评论

      • 狗妈妈2:下次看看怎么使用Rule(LinkExtractor(allow=()))
        loading_miracle: @suzysun 嗯嗯嗯
      • Carpe:666
        我才刚开始写,你就已经写完了这个脚本😂
        唉,背书做题做得脑壳疼……
        loading_miracle: @Carpe 哈哈哈,12个实验还有几篇论文,要挂科了
        Carpe: @loading_miracle 只有中午看了下爬虫,现在还在补作业刷题😂,当初脑子进的水……
        loading_miracle: @Carpe 上午上课抄了半天作业😂

      本文标题:python爬虫——知乎(关于python的精华回答)

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