爬虫基础_03——xpath

今天是利用xpath爬取网址: 简书首页
包括:标题,作者,发表时间,内容,阅读量,评论数,点赞数,打赏数,所投专题
主要思想:利用xpath获取网页中的数据,然后存到本地的csv
下面了解一下xpath的用法
首先必须要导入 lxml 库
Python爬虫利器三之Xpath语法与lxml库的用法

1、首先是爬的第一页的数据
运行代码:

#coding: utf-8
import requests
from lxml import etree
import csv


user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
header = {'User-Agent': user_agent}
html = requests.get('http://www.jianshu.com/', headers = header).content

selector = etree.HTML(html)
infos = selector.xpath('//div[@id="list-container"]/ul/li/div')
a = []
# 第一页数据的匹配
for info in infos:
    titles = info.xpath('a/text()')[0]
    authors = info.xpath('div[1]/div/a/text()')[0]
    times = info.xpath('div[1]/div/span/@data-shared-at')[0]
    contents = info.xpath('p/text()')[0].strip()
    try:
        read_counts = info.xpath('div[2]/a[2]/text()')[1].strip()
    except:
        read_counts = '0'
    try:
        comment_counts = info.xpath('div[2]/a[3]/text()')[1].strip()
    except:
        comment_counts = '0'
    try:
        vote_counts = info.xpath('//div/div[2]/span[1]/text()')[0].strip()
    except:
        vote_counts = '0'
    try:
        reward_counts = info.xpath('div[2]/span[2]/text()')[0]
    except:
        reward_counts = '0'
    try:
        subjects = info.xpath('div[2]/a[1]/text()')[0]
    except:
        subjects = '暂未收录专题'
    #print(titles, authors, times, contents, read_counts, comment_counts, vote_counts, reward_counts, subjects)

    data = {
        '文章标题': titles,
        '作者': authors,
        '发表时间': times,
        '内容': contents,
        '阅读量': read_counts,
        '评论数': comment_counts,
        '点赞数': vote_counts,
        '打赏数': reward_counts,
        '主题': subjects,

    }
    a.append(data)
#print(a)

#把爬到的数据存储到csv
csv_name = ['文章标题', '作者', '发表时间', '内容', '阅读量', '评论数', '点赞数', '打赏数', '主题']
with open('jianshu_xpath.csv', 'w', newline = '',encoding='utf-8')as csvfile:
    write = csv.DictWriter(csvfile, fieldnames = csv_name)
    write.writeheader()
    write.writerows(a)
    csvfile.close()

运行结果:

第一页的文章信息.png

第一页比较容易,主要是每个数据爬取路径的选取,还有循环点的选取;
2.爬取简书首页前15页的数据
a、首先要分析一下每页的加载方式,通过点击更多,可以发现url并没有变化,所以是异步加载,下面要抓包分析一下后面每页请求的url有什么共同点。

Paste_Image.png
Paste_Image.png

上面每页的id都可以在上一页找到,而且是会累加的,

Paste_Image.png

Paste_Image.png

具体的分析可以参看liang的文章http://www.jianshu.com/p/9afef50a8cc7,写的很详细,就不多说了;
运行代码:

#coding: utf-8
import requests
from lxml import etree
import csv


user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
header = {'User-Agent': user_agent,
          'cookie': 'remember_user_token=W1szNjE3MDgyXSwiJDJhJDEwJDMuQTVNeHVYTkUubFQvc1ZPM0V5UGUiLCIxNDk3MTcyNDA2Ljk2ODQ2NjMiXQ%3D%3D--56522c2190961ce284b1fe108b267ae0cd5bf32a; _session_id=YVRyNm5tREZkK1JwUGFZVDNLdjJoL25zVS8yMjBnOGlwSnpITEE0U0drZHhxSU5XQVpYM2RpSmY5WU44WGJWeHVZV3d1Z1lINHR0aXhUQzR6Z1pMUW52RGI5UHpPRVFJRk5HeUcybEhwc21raVBqbk9uZmhjN0xQWmc2ZFMreXhGOHlhbmJiSDBHQUVsUTNmN2p0M2Y2TjgrWnBjVis4ODE4UXRhWmJ6K2VETHJlakhHbEl0djhDNDRKYVZEWndENjhrSGIvZ1crNC9NNnh4UmlpOVFPNWxGWm1PUmxhQk1sdnk2OXozQVZwU1hXVm9lMTU3WkUyUkhialZKZ2MvVkFOYk1tOUw3STkrMGNFWXVIaklDNlNpTmkrVi9iNDIrRzBDU0ZNNnc3b3I2bkhvLzFCSCsvTWdsUDExdEZBa0RsU3RqTURWcjdNU1VOTGVBeTk2MERMUXN1UlZqUytuYXdWdnI4cTkxTjFPbG5Ia3IzK3NXcVNpMENwWVZPSUV3TWU4TENaRWUva24ybXMzSE9MTVZRSEdrVDJhMzhzM05RUnBoMk8xU1FHYz0tLTFxUnlXWTZLQXM4dW9EQmVxMHZwRWc9PQ%3D%3D--6fb5c178053ee287201628ee5d7b2b61c170e994'}

a = []
params = []
#获取每一页的url
for p in range(1,16):
    url_data = '&'.join(params)
    url = 'http://www.jianshu.com/?' + url_data + '&page={}'.format(p)
    #获取每页的数据
    html = requests.get(url, headers = header).text
    selector = etree.HTML(html)
    li_pages = selector.xpath('//div[@id="list-container"]/ul/li')
    for li_page in li_pages:
        li_page = 'seen_snote_ids[]=' + li_page.xpath('@data-note-id')[0]
        params.append(li_page)
    #print(len(params))
    infos = selector.xpath('//div[@id="list-container"]/ul/li/div')
    for info in infos:
        titles = info.xpath('a/text()')[0]
        authors = info.xpath('div[1]/div/a/text()')[0]
        times = info.xpath('div[1]/div/span/@data-shared-at')[0]
        contents = info.xpath('p/text()')[0].strip()
        try:
            read_counts = info.xpath('div[2]/a[2]/text()')[1].strip()
        except:
            read_counts = '0'
        try:
            comment_counts = info.xpath('div[2]/a[3]/text()')[1].strip()
        except:
            comment_counts = '0'
        try:
            vote_counts = info.xpath('//div/div[2]/span[1]/text()')[0].strip()
        except:
            vote_counts = '0'
        try:
                reward_counts = info.xpath('div[2]/span[2]/text()')[0]
        except:
                reward_counts = '0'
        try:
            subjects = info.xpath('div[2]/a[@class="collection-tag"]/text()')[0]
        except:
            subjects = '暂未收录专题'

        #print(titles, authors, times, contents, read_counts, comment_counts, vote_counts, reward_counts, subjects)
        data = {
            '文章标题': titles,
            '作者': authors,
            '发表时间': times,
            '内容': contents,
            '阅读量': read_counts,
            '评论数': comment_counts,
            '点赞数': vote_counts,
            '打赏数': reward_counts,
            '主题': subjects,
            }
        a.append(data)

        #存储数据
        csv_name = ['文章标题', '作者', '发表时间', '内容', '阅读量', '评论数', '点赞数', '打赏数', '主题']
        with open('jianshu_xpath2.csv', 'w', newline='', encoding='utf-8')as csvfile:
            write = csv.DictWriter(csvfile, fieldnames=csv_name)
            write.writeheader()
            write.writerows(a)


运行结果:

简书首页所有的文章信息.png

注意这里取cookie的时候一定要登录后再取cookie,否则只能爬到重复第一页的数据;
最后再把整个代码整理封装一下,稍微好看一点:

#coding: utf-8
import requests
from lxml import etree
import csv

class Jianshu():

    user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
    header = {'User-Agent': user_agent,
              'cookie': 'remember_user_token=W1szNjE3MDgyXSwiJDJhJDEwJDMuQTVNeHVYTkUubFQvc1ZPM0V5UGUiLCIxNDk3MTcyNDA2Ljk2ODQ2NjMiXQ%3D%3D--56522c2190961ce284b1fe108b267ae0cd5bf32a; _session_id=YVRyNm5tREZkK1JwUGFZVDNLdjJoL25zVS8yMjBnOGlwSnpITEE0U0drZHhxSU5XQVpYM2RpSmY5WU44WGJWeHVZV3d1Z1lINHR0aXhUQzR6Z1pMUW52RGI5UHpPRVFJRk5HeUcybEhwc21raVBqbk9uZmhjN0xQWmc2ZFMreXhGOHlhbmJiSDBHQUVsUTNmN2p0M2Y2TjgrWnBjVis4ODE4UXRhWmJ6K2VETHJlakhHbEl0djhDNDRKYVZEWndENjhrSGIvZ1crNC9NNnh4UmlpOVFPNWxGWm1PUmxhQk1sdnk2OXozQVZwU1hXVm9lMTU3WkUyUkhialZKZ2MvVkFOYk1tOUw3STkrMGNFWXVIaklDNlNpTmkrVi9iNDIrRzBDU0ZNNnc3b3I2bkhvLzFCSCsvTWdsUDExdEZBa0RsU3RqTURWcjdNU1VOTGVBeTk2MERMUXN1UlZqUytuYXdWdnI4cTkxTjFPbG5Ia3IzK3NXcVNpMENwWVZPSUV3TWU4TENaRWUva24ybXMzSE9MTVZRSEdrVDJhMzhzM05RUnBoMk8xU1FHYz0tLTFxUnlXWTZLQXM4dW9EQmVxMHZwRWc9PQ%3D%3D--6fb5c178053ee287201628ee5d7b2b61c170e994'}

    a = []
    params = []
    def __init__(self):
        pass
    #获取每一页的url
    def total_page(self):
        for p in range(1,16):
            url_data = '&'.join(self.params)
            url = 'http://www.jianshu.com/?' + url_data + '&page={}'.format(p)
            self.get_data(url)
    #获取每页的数据
    def get_data(self, url):
        html = requests.get(url, headers = self.header).text
        selector = etree.HTML(html)
        li_pages = selector.xpath('//*[@id="list-container"]/ul/li')
            #print(li_pages)
        for info in li_pages:
            info = 'seen_snote_ids%5B%5D=' + info.xpath('@data-note-id')[0]
            self.params.append(info)
        infos = selector.xpath('//div[@id="list-container"]/ul/li/div')
        for info in infos:
            titles = info.xpath('a/text()')[0]
            authors = info.xpath('div[1]/div/a/text()')[0]
            times = info.xpath('div[1]/div/span/@data-shared-at')[0]
            contents = info.xpath('p/text()')[0].strip()
            try:
                read_counts = info.xpath('div[2]/a[2]/text()')[1].strip()
            except:
                read_counts = '0'
            try:
                comment_counts = info.xpath('div[2]/a[3]/text()')[1].strip()
            except:
                comment_counts = '0'
            try:
                vote_counts = info.xpath('//div/div[2]/span[1]/text()')[0].strip()
            except:
                vote_counts = '0'
            try:
                reward_counts = info.xpath('div[2]/span[2]/text()')[0]
            except:
                reward_counts = '0'
            try:
                subjects = info.xpath('div[2]/a[@class="collection-tag"]/text()')[0]
            except:
                subjects = '暂未收录专题'

            #print(titles, authors, times, contents, read_counts, comment_counts, vote_counts, reward_counts, subjects)
            data = {
                '文章标题': titles,
                '作者': authors,
                '发表时间': times,
                '内容': contents,
                '阅读量': read_counts,
                '评论数': comment_counts,
                '点赞数': vote_counts,
                '打赏数': reward_counts,
                '主题': subjects,
                }
            self.a.append(data)
            #print(self.a)
            #存储数据
            csv_name = ['文章标题', '作者', '发表时间', '内容', '阅读量', '评论数', '点赞数', '打赏数', '主题']
            with open('jianshu_xpath2.csv', 'w', newline='', encoding='utf-8')as csvfile:
                write = csv.DictWriter(csvfile, fieldnames=csv_name)
                write.writeheader()
                write.writerows(self.a)

if __name__ == '__main__':
    jian = Jianshu()
    jian.total_page()

小结:
1、这里用xpath爬取网页的内容,是不是很方便?
虽然用正则、BeautifulSoup和Xpath都可以获取网页的内容,但是要学会灵活应用,有时遇到某一种方法获取不到就要用另外的方法(比如正则,只要你的正则表达式没写错,基本都是可以获取网页数据)
2、这里爬取多页是通过自己手动分析网页加载方式去构造每页的url,然后爬取全部的数据;对于这种异步加载的网页,后面还会介绍其他的方法;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容