摘要:此案例是爬取目標網站(https://tipdm.com/
)的新聞中心板塊的公司新聞中所有新聞的標題、發(fā)布時間、訪問量和新聞的文本內容。
1. 創(chuàng)建scrapy項目
我使用的是 Anaconda prompt
我們使用如下命令創(chuàng)建scrapy項目:scrapy startproject spider_name 爬蟲路徑
spider_name
是項目的名字爬蟲路徑
就是項目所在位置
本案例內命令是:scrapy startproject mySpider 路徑
2. 生成爬蟲器
我們先生成 spider(爬蟲器)
文件:scrapy genspider spider_name domain
spider_name
:是生成的 爬蟲器的名字,在目錄spiders
下面domain
:是要爬取的網站的域名(一般是不加http,只寫www.xxx.com就行)
本案例內,命令是scrapy genspider msd www.tipdm.com
3. 指定爬取字段(items.py)
指定要爬取的內容都有什么,我們在摘要中已經說明,要爬取的是 所有新聞的標題、發(fā)布時間、訪問量和新聞的文本內容
。
所以有四個字段,代碼如下:
import scrapy
class MyspiderItem(scrapy.Item):
title = scrapy.Field()
time = scrapy.Field()
view = scrapy.Field()
text = scrapy.Field()
4. 編寫爬蟲文件(msd.py)
我們要爬取的是:所有頁面的、所有新聞的內容。
所以我們寫三個parse
函數(shù)。
-
parse
:得到頁數(shù),并得到每頁的網址,傳給下個函數(shù) -
parse_url
:得到每個頁面的所有新聞的鏈接 -
parse_text
:分析得到的新聞界面的內容,并存入item
中,返回回去
注意:將 start_url
修改成第一個要爬取的頁面,即公司新聞的頁面
(代碼中注釋掉的內容都是調試用的)
parse函數(shù)
先得到總頁數(shù),因為取出來的是 str,將其轉成int類型。
通過取出各個頁面可知,每個頁面的網址類似,只有數(shù)字不同,我們就可以生成網址了。
然后使用 yield Request()
回調下一個函數(shù)。
現(xiàn)在還不太懂原理。yield
,并不會直接返回,而是會返回一個生成器,可以遍歷完所有的網頁再統(tǒng)一返回
def parse(self, response):
number = int(response.xpath('//*[@id="t251"]/div[6]/div/a[6]/text()').extract()[0]) # 總頁數(shù)
url_all = ['http://www.tipdm.com/gsxw/index_{}.jhtml'.format(i) for i in range(1, number + 1)]
for i in url_all:
yield Request(url=i, callback=self.parse_url, dont_filter=True)
parse_url
得到單個頁面中的所有新聞的網址,放在一個列表中
注意:這里被卡了好久,就是因為得到的網址是不完整的,沒有前綴(http之類的)一直進不到下一個函數(shù)(可以在每個函數(shù)寫一個輸出語句,以便檢查是否進入了函數(shù))
所以我們將url補充完畢,進行回調
爬取不出來的時候,一定要輸出一下網址看看
def parse_url(self, response):
urls = response.xpath('//*[@id="t251"]/div/div[3]/h1/a/@href').extract()
for i in urls:
yield Request(url=('http://www.tipdm.com' + i), callback=self.parse_text, dont_filter=True)
parse_text
本函數(shù)是分析新聞的內容的函數(shù),并存儲在item
中返回
有個很尷尬的點是這個網站的前端有點亂,有幾條新聞的文本內容的xpath
路徑和其他的都不一樣,好麻煩的,現(xiàn)在還不知道怎么解決
def parse_text(self, response):
item = MyspiderItem()
item['title'] = response.xpath('/html/body/div[2]/div/div[1]/div[2]/h1/text()').extract() # title
item['time'] = response.xpath('/html/body/div[2]/div/div[1]/div[2]/div/div[1]/span[1]/text()').extract() # time
item['view'] = response.xpath('/html/body/div[2]/div/div[1]/div[2]/div/div[1]/span[3]/text()').extract() # view
item['text'] = '\n'.join(response.xpath('/html/body/div[2]/div/div[2]/p/text()').extract())
if item['text'] == '':
item['text'] = '\n'.join(response.xpath('/html/body/div[2]/div/div[2]/p/span/text()').extract())
if item['text'] == '':
item['text'] = '\n'.join(response.xpath('/html/body/div[2]/div/div[2]/section[2]/section/section[2]/section[2]/p/span/text()').extract())
return item
完整代碼
import scrapy
from scrapy.http import Request
from mySpider.items import MyspiderItem
class MsdSpider(scrapy.Spider):
name = 'msd'
allowed_domains = ['www.tipdm.com']
start_urls = ['http://www.tipdm.com/gsxw/index.jhtml']
def parse(self, response):
number = int(response.xpath('//*[@id="t251"]/div[6]/div/a[6]/text()').extract()[0]) # 總頁數(shù)
url_all = ['http://www.tipdm.com/gsxw/index_{}.jhtml'.format(i) for i in range(1, number + 1)]
for i in url_all:
# print('1111111111111111')
yield Request(url=i, callback=self.parse_url, dont_filter=True)
# print(i)
def parse_url(self, response):
urls = response.xpath('//*[@id="t251"]/div/div[3]/h1/a/@href').extract()
# print('22222222222222222222')
for i in urls:
yield Request(url=('http://www.tipdm.com' + i), callback=self.parse_text, dont_filter=True)
def parse_text(self, response):
# print('77')
item = MyspiderItem()
# print('78')
item['title'] = response.xpath('/html/body/div[2]/div/div[1]/div[2]/h1/text()').extract() # title
# print('7999')
item['time'] = response.xpath('/html/body/div[2]/div/div[1]/div[2]/div/div[1]/span[1]/text()').extract() # time
item['view'] = response.xpath('/html/body/div[2]/div/div[1]/div[2]/div/div[1]/span[3]/text()').extract() # view
item['text'] = '\n'.join(response.xpath('/html/body/div[2]/div/div[2]/p/text()').extract())
if item['text'] == '':
item['text'] = '\n'.join(response.xpath('/html/body/div[2]/div/div[2]/p/span/text()').extract())
if item['text'] == '':
item['text'] = '\n'.join(response.xpath('/html/body/div[2]/div/div[2]/section[2]/section/section[2]/section[2]/p/span/text()').extract())
# print('79')
return item
5. 存儲數(shù)據(jù)(pipelines.py、settings.py)
我們選擇使用pipelines
存儲,需要在settings
文件中取消相應代碼注釋
settings.py
ITEM_PIPELINES = {
'mySpider.pipelines.MyspiderPipeline': 300,
}
pipelines.py
因為我選擇存儲為.csv
文件,所以需要導入pandas
注意:to_csv
中,參數(shù)順序不能亂文章來源:http://www.zghlxwxcb.cn/news/detail-419818.html
其中,參數(shù)的順序如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-419818.html
filename
: 文件名,必需。index
: 是否寫入行索引,可選。默認為False
。encoding
: 字符編碼,可選。默認為utf-8-sig
。compression
: 壓縮模式,可選。默認為gzip
。header
: 表頭是否寫入,可選。默認為None
。footer
: 表尾是否寫入,可選。默認為None
。newline
: 換行符,可選。默認為None
。dtype
: 數(shù)據(jù)類型,可選。默認為None
。optimizer
: 優(yōu)化器,可選。默認為None
。寫入文件的寫入器對象
: 寫入文件的寫入器對象,可選。默認為None
。寫入文件的參數(shù)
: 寫入文件的參數(shù),可選。默認為None
。
需要注意的是,header
和footer
參數(shù)默認為None
,表示不寫入表頭和表尾。如果希望寫入表頭或表尾,可以設置該參數(shù)為True
。
import pandas as pd
from itemadapter import ItemAdapter
class MyspiderPipeline:
def process_item(self, item, spider):
data = pd.DataFrame(dict(item))
data.to_csv('data2.csv', mode='a+', index=None, encoding='utf-8-sig', header=None)
return item
到了這里,關于scrapy爬蟲爬取多網頁內容的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!