python获取id标签对应数据_Python--Scrapy爬虫获取简书作者ID的全部文章列表数据
最近Python大火,為了跟上時(shí)代,試著自學(xué)了下。Scrapy是一個(gè)高級(jí)的Python爬蟲框架,它不僅包含了爬蟲的特性,還可以方便的將爬蟲數(shù)據(jù)保存到csv、json等文件中。
今天我們就試著用Scrapy來(lái)爬取簡(jiǎn)書某位作者的全部文章。
在本篇教程中,我們假定您已經(jīng)安裝好Scrapy。 如若不然,請(qǐng)參考 安裝指南 。
1.創(chuàng)建項(xiàng)目
在開(kāi)始爬取之前,我們必須創(chuàng)建一個(gè)新的Scrapy項(xiàng)目,我這里命名為jianshu_article。打開(kāi)Mac終端,cd到你打算存儲(chǔ)代碼的目錄中,運(yùn)行下列命令:
//Mac終端運(yùn)行如下命令:
scrapy startproject jianshu_article
2.創(chuàng)建爬蟲程序
//cd到上面創(chuàng)建的文件目錄
cd jianshu_article
//創(chuàng)建爬蟲程序
scrapy genspider jianshu jianshu.com
/*
文件說(shuō)明:
scrapy.cfg 項(xiàng)目的配置信息,主要為Scrapy命令行工具提供一個(gè)基礎(chǔ)的配置信息。(真正爬蟲相關(guān)的配置信息在settings.py文件中)
items.py 設(shè)置數(shù)據(jù)存儲(chǔ)模型,用于結(jié)構(gòu)化數(shù)據(jù),如:Django的Model
pipelines 數(shù)據(jù)處理行為,如:一般結(jié)構(gòu)化的數(shù)據(jù)持久化
settings.py 配置文件,如:USER_AGENT(模擬瀏覽器,應(yīng)對(duì)網(wǎng)站反爬),遞歸的層數(shù)、并發(fā)數(shù),延遲下載等
spiders 爬蟲目錄,如:創(chuàng)建文件,編寫爬蟲規(guī)則
*/
為了方便編寫程序,我們用Pycharm打開(kāi)項(xiàng)目,執(zhí)行完上面的命令程序會(huì)自動(dòng)創(chuàng)建目錄及文件,其中生成了一個(gè)jianshu.py的文件,后面我們主要邏輯都將寫在此文件中。
jianshu.py
3.設(shè)置數(shù)據(jù)模型
雙擊items.py文件。
找到你想爬取的簡(jiǎn)書作者首頁(yè),如我自己的首頁(yè)https://www.jianshu.com/u/6b14223f1b58,用谷歌瀏覽器打開(kāi),空白處鼠標(biāo)右擊,單擊“檢查”進(jìn)入控制臺(tái)開(kāi)發(fā)者模式:
打開(kāi)控制臺(tái).png
通過(guò)分析網(wǎng)頁(yè)源碼,我們大概需要這些內(nèi)容:
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html
import scrapy
class JianshuArticalItem(scrapy.Item):
avatar = scrapy.Field() #頭像
nickname = scrapy.Field() #昵稱
time = scrapy.Field() #發(fā)表時(shí)間
wrap_img = scrapy.Field() #封面(缺省值)
title = scrapy.Field() #標(biāo)題
abstract = scrapy.Field() #正文部分顯示
read = scrapy.Field() #查看人數(shù)
comments = scrapy.Field() #評(píng)論數(shù)
like = scrapy.Field() #喜歡(點(diǎn)贊)
detail = scrapy.Field() #文章詳情url
pass
如此數(shù)據(jù)模型就創(chuàng)建好了,后面運(yùn)行爬蟲的時(shí)候,我得到的數(shù)據(jù)將存進(jìn)模型對(duì)應(yīng)的位置。
4.分析網(wǎng)頁(yè)源碼,編寫爬蟲
因?yàn)楸救吮容^懶很少寫文章,文章數(shù)比較少,為了呈現(xiàn)分頁(yè)的效果,我在簡(jiǎn)書選取了一位作者CC老師_MissCC的主頁(yè)進(jìn)行爬取。
我們通過(guò)分析URL可以找到一些特征:
作者的URL為:https://www.jianshu.com/u/ + 作者ID:
作者主頁(yè)URL.png
文章URL.png
雖然我們?cè)跒g覽器直接打開(kāi)作者的URL,鼠標(biāo)滾輪往下滾動(dòng)會(huì)動(dòng)態(tài)加載下一頁(yè)直至最后一篇文章URL還是保持不變。但是作為Scrapy爬蟲貌似只能拿到第一頁(yè),那么如何做到呢?以我個(gè)人多年的開(kāi)發(fā)經(jīng)驗(yàn)我嘗試在URL后面拼接一個(gè)"page"參數(shù)加上頁(yè)數(shù),果不其然,能請(qǐng)求到不同的數(shù)據(jù)。
拼接參數(shù)page拿到分頁(yè)數(shù)據(jù).png
找到這些規(guī)律,我們就可以通過(guò)分析HTML源碼,拿到我們想要的數(shù)據(jù)了。
首先,我們回到j(luò)ianshu.py這個(gè)文件,導(dǎo)入模型:
//從項(xiàng)目名 jianshu_article的文件items.py導(dǎo)入JianshuArticleItem類
from jianshu_article.items import JianshuArticleItem
設(shè)置必要參數(shù)發(fā)起首次請(qǐng)求:
# -*- coding: utf-8 -*-
import scrapy
from jianshu_article.items import JianshuArticleItem
class JianshuSpider(scrapy.Spider):
name = 'jianshu'
allowed_domains = ['jianshu.com']
user_id = "1b4c832fb2ca"
url = "https://www.jianshu.com/u/{0}?page=1".format(user_id)
start_urls = [
url,
]
def parse(self, response):
#用戶頭像
c = response.xpath('//div[@class="main-top"]/a[@class="avatar"]/img/@src').extract_first()
print(c)
pass
至此終端運(yùn)行命令scrapy crawl jianshu,理論上可以打印網(wǎng)頁(yè)內(nèi)容。實(shí)則不然,沒(méi)有請(qǐng)求到任何數(shù)據(jù),終端會(huì)打印一些日志信息:
日志.png
不難發(fā)現(xiàn),報(bào)了403的問(wèn)題和HTTP status code is not handled or not allowed的問(wèn)題,導(dǎo)致"Closing spider (finished)"爬蟲終止。通過(guò)萬(wàn)能百度,我知道大概是網(wǎng)站做了一些相應(yīng)的反爬蟲的措施導(dǎo)致的。對(duì)癥下藥,我們只需要在settings.py,做一些相應(yīng)修改就可以了:
```
User_Agent中文名為用戶代理,簡(jiǎn)稱 UA,它是一個(gè)特殊字符串頭,使得服務(wù)器能夠識(shí)別客戶使用的
操作系統(tǒng)及版本、CPU 類型、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語(yǔ)言、瀏覽器插件等。
通俗點(diǎn)講,我們配置這個(gè)字段的目的就是為了偽裝成瀏覽器打開(kāi)網(wǎng)頁(yè),達(dá)到騙過(guò)目標(biāo)網(wǎng)站的監(jiān)測(cè)。
```
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'
CONCURRENT_REQUESTS = 1 #并發(fā)數(shù)
DOWNLOAD_DELAY = 5 #為了防止IP被封,我們5秒請(qǐng)求一次
HTTPERROR_ALLOWED_CODES = [403] #上面報(bào)的是403,就把403加入
#默認(rèn)為True,就是要遵守robots.txt 的規(guī)則,這里我們改為False
ROBOTSTXT_OBEY = False
做了相應(yīng)的修改,我們?cè)俅螆?zhí)行爬蟲命令:scrapy crawl jianshu ,看日志打印獲取到頭像。
獲取到頭像.png
既然網(wǎng)頁(yè)數(shù)據(jù)能爬取成功,我們后面要做的只是分析網(wǎng)頁(yè)源碼了,下面就不一一去分析了,體力活。當(dāng)然在此之前你要對(duì)xpath有一定的了解。
下面引用Scrapy中文官網(wǎng)介紹:
從網(wǎng)頁(yè)中提取數(shù)據(jù)有很多方法。Scrapy使用了一種基于 XPath 和 CSS 表達(dá)式機(jī)制: Scrapy Selectors。 關(guān)于selector和其他提取機(jī)制的信息請(qǐng)參考 Selector文檔 。
這里給出XPath表達(dá)式的例子及對(duì)應(yīng)的含義:
/html/head/title: 選擇HTML文檔中
標(biāo)簽內(nèi)的 元素/html/head/title/text(): 選擇上面提到的
元素的文字//td: 選擇所有的
元素//div[@class="mine"]: 選擇所有具有 class="mine" 屬性的 div 元素
上邊僅僅是幾個(gè)簡(jiǎn)單的XPath例子,XPath實(shí)際上要比這遠(yuǎn)遠(yuǎn)強(qiáng)大的多。 如果您想了解的更多,我們推薦 這篇XPath教程 。
通過(guò)上面的介紹,相信你可以做接下來(lái)的爬蟲工作了,下面貼上jianshu.py的全部代碼,以供參考:
# -*- coding: utf-8 -*-
import scrapy
from jianshu_article.items import JianshuArticleItem
class JianshuSpider(scrapy.Spider):
name = 'jianshu'
allowed_domains = ['jianshu.com']
user_id = "1b4c832fb2ca" #替換此用戶ID可獲取你需要的數(shù)據(jù),或者放開(kāi)下一行的注釋
#user_id = input('請(qǐng)輸入作者id:\n')
url = "https://www.jianshu.com/u/{0}?page=1".format(user_id)
start_urls = [
url,
]
def parse(self, response):
# [關(guān)注,粉絲,文章]
a = response.xpath('//div[@class="main-top"]/div[@class="info"]/ul/li/div/a/p/text()').extract()
print(a)
# [字?jǐn)?shù),收獲喜歡]
b = response.xpath('//div[@class="main-top"]/div[@class="info"]/ul/li/div/p/text()').extract()
print(b)
# 大頭像
c = response.xpath('//div[@class="main-top"]/a[@class="avatar"]/img/@src').extract_first()
print(c)
# 用戶名
d = response.xpath('//div[@class="main-top"]/div[@class="title"]/a/text()').extract_first()
print(d)
# 性別
e = response.xpath('//div[@class="main-top"]/div[@class="title"]/i/@class').extract_first()
print(e)
# 獲取文章總數(shù),計(jì)算頁(yè)數(shù)。(簡(jiǎn)書網(wǎng)站默認(rèn)每頁(yè)是9組數(shù)據(jù))
temp = int(a[2])
if (temp % 9 > 0):
count = temp // 9 + 1
else:
count = temp // 9
print("總共" + str(count) + "頁(yè)")
base_url = "https://www.jianshu.com/u/{0}?page={1}"
for i in range(1, count + 1):
i = count + 1 - i #理論上正序1~count就是按順序獲取的,但是獲取的數(shù)據(jù)是倒置的,所以我們獲取count~1的數(shù)據(jù),得到的數(shù)組就是按照網(wǎng)頁(yè)形式1~count頁(yè)碼排序的了
yield scrapy.Request(base_url.format(self.user_id, i), dont_filter=True, callback=self.parse_page)
#迭代返回每頁(yè)的內(nèi)容
def parse_page(self, response):
for sel in response.xpath('//div[@id="list-container"]/ul/li'):
item = JianshuArticleItem()
item['wrap_img'] = sel.xpath('a/img/@src').extract_first()
item['avatar'] = sel.xpath('div//a[@class="avatar"]/img/@src').extract_first()
item['nickname'] = sel.xpath('div//a[@class="nickname"]/text()').extract_first()
item['time'] = sel.xpath('div//span[@class="time"]/@data-shared-at').extract_first()
item['title'] = sel.xpath('div/a[@class="title"]/text()').extract_first()
item['abstract'] = sel.xpath('div/p[@class="abstract"]/text()').extract_first()
item['read'] = sel.xpath('div/div[@class="meta"]/a[1]/text()').extract()[1]
item['comments'] = sel.xpath('div/div[@class="meta"]/a[2]/text()').extract()[1]
item['like'] = sel.xpath('div/div[@class="meta"]/span/text()').extract_first()
item['detail'] = sel.xpath('div/a[@class="title"]/@href').extract_first()
yield item
至此爬蟲代碼編寫完畢,如果要把獲取的數(shù)據(jù)保存下來(lái),你可以終端執(zhí)行如下命令:
/*
此命令用于把爬取的數(shù)據(jù)保存為json文件格式,當(dāng)然你也可以保存為別的文件格式。
Scrapy官方列出的文件格式有如下幾種:('json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle')。
溫馨提示:如果要再次爬取,最好換一個(gè)文件名或者清空數(shù)據(jù)再爬取,因?yàn)榈诙€是寫入上一個(gè)文件,數(shù)據(jù)不會(huì)覆蓋,
會(huì)堆積在上次獲取的下面,造成json文件格式報(bào)錯(cuò)。
*/
scrapy crawl jianshu -o data.json
程序執(zhí)行完后,我們可以在文件目錄看到新生成的data.json文件,雙擊可以看到我們要獲取的全部數(shù)據(jù):
執(zhí)行爬蟲獲取到的數(shù)據(jù).png
json解析數(shù)據(jù)跟網(wǎng)站上的完全吻合.png
github地址:https://github.com/leesonp/jianshu_article
至此以上就是本文的全部?jī)?nèi)容,謝謝閱讀。
總結(jié)
以上是生活随笔為你收集整理的python获取id标签对应数据_Python--Scrapy爬虫获取简书作者ID的全部文章列表数据的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 一位被信息时代遗忘的隐秘天才,一个为人类
- 下一篇: “杨振宁理论物理研究所”