言
文的文字及圖片來(lái)源于網(wǎng)絡(luò),僅供學(xué)習(xí)、交流使用,不具有任何商業(yè)用途,版權(quán)歸原作者所有,如有問(wèn)題請(qǐng)及時(shí)聯(lián)系我們以作處理。
作者: 風(fēng),又奈何
PS:如有需要Python學(xué)習(xí)資料的小伙伴可以加點(diǎn)擊下方鏈接自行獲取
http://note.youdao.com/noteshare?id=3054cce4add8a909e784ad934f956cef
準(zhǔn)備
項(xiàng)目創(chuàng)建:
cmd命令行切換到工作目錄創(chuàng)建scrapy項(xiàng)目 兩條命令 scarpy startproject與scrapy genspider 然后用pycharm打開(kāi)項(xiàng)目
D:\pythonwork>scrapy startproject zongheng New Scrapy project 'zongheng', using template directory 'c:\users\11573\appdata\local\programs\python\python36\lib\site-packages\scrapy\templates\project', created in: D:\pythonwork\zongheng You can start your first spider with: cd zongheng scrapy genspider example example.com D:\pythonwork>cd zongheng D:\pythonwork\zongheng>cd zongheng D:\pythonwork\zongheng\zongheng>scrapy genspider xuezhong http://book.zongheng.com/chapter/189169/3431546.html Created spider 'xuezhong' using template 'basic' in module: zongheng.spiders.xuezhong
確定內(nèi)容
首先打開(kāi)網(wǎng)頁(yè)看下我們需要爬取的內(nèi)容
其實(shí)小說(shuō)的話(huà)結(jié)構(gòu)比較簡(jiǎn)單 只有三大塊 卷 章節(jié) 內(nèi)容
因此 items.py代碼:
內(nèi)容提取spider文件編寫(xiě)
還是我們先創(chuàng)建一個(gè)main.py文件方便我們測(cè)試代碼
然后我們可以在spider文件中先編寫(xiě)
# -*- coding: utf-8 -*- import scrapy class XuezhongSpider(scrapy.Spider): name='xuezhong' allowed_domains=['http://book.zongheng.com/chapter/189169/3431546.html'] start_urls=['http://book.zongheng.com/chapter/189169/3431546.html/'] def parse(self, response): print(response.text) pass
運(yùn)行main.py看看有沒(méi)有輸出
發(fā)現(xiàn)直接整個(gè)網(wǎng)頁(yè)的內(nèi)容都可以爬取下來(lái),說(shuō)明該網(wǎng)頁(yè)基本沒(méi)有反爬機(jī)制,甚至不用我們?nèi)バ薷膗ser-agent那么就直接開(kāi)始吧
打開(kāi)網(wǎng)頁(yè) F12查看元素位置 并編寫(xiě)xpath路徑 然后編寫(xiě)spider文件
需要注意的是我們要對(duì)小說(shuō)內(nèi)容進(jìn)行一定量的數(shù)據(jù)清洗,因?yàn)榘承﹉tml標(biāo)簽我們需要去除
# -*- coding: utf-8 -*- import scrapy import re from zongheng.items import ZonghengItem class XuezhongSpider(scrapy.Spider): name='xuezhong' allowed_domains=['book.zongheng.com'] start_urls=['http://book.zongheng.com/chapter/189169/3431546.html/'] def parse(self, response): xuezhong_item=ZonghengItem() xuezhong_item['book']=response.xpath('//*[@id="reader_warp"]/div[2]/text()[4]').get()[3:] xuezhong_item['section']=response.xpath('//*[@id="readerFt"]/div/div[2]/div[2]/text()').get() content=response.xpath('//*[@id="readerFt"]/div/div[5]').get() #content內(nèi)容需要處理因?yàn)闀?huì)顯示標(biāo)簽和標(biāo)簽 content=re.sub(r'', "", content) content=re.sub(r'',"\n",content ) xuezhong_item['content']=content yield xuezhong_item nextlink=response.xpath('//*[@id="readerFt"]/div/div[7]/a[3]/@href').get() print(nextlink) if nextlink: yield scrapy.Request(nextlink,callback=self.parse)|
|
有時(shí)候我們會(huì)發(fā)現(xiàn)無(wú)法進(jìn)入下個(gè)鏈接,那可能是被allowed_domains過(guò)濾掉了 我們修改下就可以
唉 突然發(fā)現(xiàn)了到第一卷的一百多章后就要VIP了 那我們就先只弄一百多章吧 不過(guò)也可以去其他網(wǎng)站爬取免費(fèi)的 這次我們就先爬取一百多章吧
內(nèi)容保存
接下來(lái)就是內(nèi)容的保存了,這次就直接保存為本地txt文件就行了
首先去settings.py文件里開(kāi)啟 ITEM_PIPELINES
然后編寫(xiě)pipelines.py文件
# -*- coding: utf-8 -*- class ZonghengPipeline(object): def process_item(self, item, spider): filename=item['book']+item['section']+'.txt' with open("../xuezhongtxt/"+filename,'w') as txtf: txtf.write(item['content']) return item
由于選址失誤導(dǎo)致了我們只能爬取免費(fèi)的一百多章節(jié),尷尬,不過(guò)我們可以類(lèi)比運(yùn)用到其他網(wǎng)站爬取全文免費(fèi)的書(shū)籍
怎么樣 使用scrapy爬取是不是很方便呢
.
文為php中文網(wǎng)認(rèn)證作者:“L先生”投稿,歡迎加入php中文網(wǎng)有償投稿計(jì)劃!
有人習(xí)慣看小說(shuō),偶爾會(huì)看幾章,都是百度出來(lái),但是基本都有特別煩人的廣告,要么在整體div添加鏈接,誤觸就會(huì)跳轉(zhuǎn)到一些網(wǎng)站甚至是死循環(huán),某些手機(jī)app也是廣告很多,所以無(wú)事在寫(xiě)一個(gè)小程序免除廣告的煩擾
本文將使用php curl采集頁(yè)面simple_html_dom解析,實(shí)現(xiàn)真正的去除廣告。
隨便找一個(gè)小說(shuō)網(wǎng)站找一本書(shū),不過(guò)這個(gè)站點(diǎn)在手機(jī)端是特別坑的,就有上述問(wèn)題:
就拿這本小說(shuō)來(lái)開(kāi)刀。(聲明:絕對(duì)不是推廣,侵刪)
一、了解curl的get方式
curl是一個(gè)命令行工具,通過(guò)指定的URL來(lái)上傳或下載數(shù)據(jù),并將數(shù)據(jù)展示出來(lái)。curl中的c表示client,而URL,就是URL。
PHP中使用cURL可以實(shí)現(xiàn)Get和Post請(qǐng)求的方法
簡(jiǎn)單的抓取小說(shuō)僅需要get方法即可。
下面這個(gè)示例代碼就是通過(guò)get請(qǐng)求獲取第一章小說(shuō)頁(yè)面html的示例,只需要更改url參數(shù)即可。
初始化、設(shè)置選項(xiàng)、證書(shū)驗(yàn)證、執(zhí)行、關(guān)閉
<?php
header("Content-Type:text/html;charset=utf-8");
$url="https://www.7kzw.com/85/85445/27248636.html";
$ch=curl_init($url); //初始化
//設(shè)置選項(xiàng)
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//獲取的信息以字符串返回,而不是直接輸出(必須)
curl_setopt($ch,CURLOPT_TIMEOUT,10);//超時(shí)時(shí)間(必須)
curl_setopt($ch, CURLOPT_HEADER,0);// 啟用時(shí)會(huì)將頭文件的信息作為數(shù)據(jù)流輸出。
//參數(shù)為1表示輸出信息頭,為0表示不輸出
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); //不驗(yàn)證證書(shū)
// 3.執(zhí)行
$res=curl_exec($ch);
// 4.關(guān)閉
curl_close($ch);
print_r($res);
?>
注釋就特別詳細(xì)了,按照步驟,發(fā)送curl的get請(qǐng)求,如果是post請(qǐng)求則需要多加一條設(shè)置post選項(xiàng)的設(shè)置,并且傳參,最后輸出獲得的信息,運(yùn)行結(jié)果如下,是沒(méi)有css渲染的。
二、解析頁(yè)面
輸出的頁(yè)面有很多不需要的內(nèi)容,需要在所有內(nèi)容中提取出我們需要的內(nèi)容,比如標(biāo)題和每章的內(nèi)容,這時(shí)需要解析頁(yè)面。
解析頁(yè)面的方法也有很多,在這里使用的是simple_html_dom,需要下載引用simple_html_dom.php這個(gè)類(lèi),實(shí)例對(duì)象,并調(diào)用內(nèi)部的方法。具體方法可以到官網(wǎng)查看,或者中文網(wǎng)其他文檔。
先分析這個(gè)小說(shuō)頁(yè)面的源代碼,看這章的標(biāo)題和內(nèi)容對(duì)應(yīng)的元素
首先是標(biāo)題:在類(lèi)bookname下的h1下
然后是內(nèi)容:在id為content的div下
simple_html_dom的可以使用find方法,類(lèi)似jquery一樣使用選擇器查找定位元素。如:
find('.bookname h1'); //查找類(lèi)bookname 下的h1標(biāo)題元素
find('#content'); //查找id為content的章節(jié)內(nèi)容
代碼在以上的基礎(chǔ)上新增:
include "simple_html_dom.php";
$html=new simple_html_dom();
@$html->load($res);
$h1=$html->find('.bookname h1');
foreach ($h1 as $k=>$v) {
$artic['title']=$v->innertext;
}
// 查找小說(shuō)的具體內(nèi)容
$divs=$html->find('#content');
foreach ($divs as $k=>$v) {
$content=$v->innertext;
}
// 正則替換去除多余部分
$pattern="/(<p>.*?<\/p>)|(<div .*?>.*?<\/div>)/";
$artic['content']=preg_replace($pattern,'',$content);
echo $artic['title'].'<br>';
echo $artic['content'];
使用以上的解析方法獲得的內(nèi)容是數(shù)組,使用foreach來(lái)獲得數(shù)組內(nèi)容,使用了正則替換將正文文字廣告去除,將標(biāo)題和小說(shuō)內(nèi)容放到數(shù)組內(nèi)。最簡(jiǎn)單的寫(xiě)法就寫(xiě)好了。運(yùn)行結(jié)果如下:
當(dāng)然這種寫(xiě)法看著比較難受,可以自行封裝函數(shù)類(lèi)。如下就是我自己寫(xiě)好的代碼示例了,當(dāng)然肯定有不足的地方,但是可以作為參考擴(kuò)展。
<?php
include "simple_html_dom.php";
include "mySpClass.php";
header("Content-Type:text/html;charset=utf-8");
$get_html=get_html($_GET['n']);
$artic=getContent($get_html);
echo $artic['title'].'<br>';
echo $artic['content'];
/**
* 獲取www.7kzw.com 獲取每一章的頁(yè)面html
* @param type $num 第幾章,從第一開(kāi)始(int)
* @return 返回字符串
*/
function get_html($num){
$start=27248636;
$real_num=$num+$start-1;
$url='https://www.7kzw.com/85/85445/'.$real_num.'.html';
$header=[
'User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0'
];
return mySpClass()->getCurl($url,$header);
}
/**
* 獲取www.7kzw.com小說(shuō)標(biāo)題數(shù)組
* @param type $get_html 得到的每一章的頁(yè)面html
* @return 返回$artic數(shù)組,['title'=>'','content'=>'']
*/
function getContent($get_html){
$html=new simple_html_dom();
@$html->load($get_html);
$h1=$html->find('.bookname h1');
foreach ($h1 as $k=>$v) {
$artic['title']=$v->innertext;
}
// 查找小說(shuō)的具體內(nèi)容
$divs=$html->find('#content');
foreach ($divs as $k=>$v) {
$content=$v->innertext;
}
// 正則替換去除多余部分
$pattern="/(<p>.*?<\/p>)|(<div .*?>.*?<\/div>)/";
$artic['content']=preg_replace($pattern,'',$content);
return $artic;
}
?>
<?php
class mySpClass{
//單例對(duì)象
private static $ins=null;
/**
* 單例化對(duì)象
*/
public static function exec()
{
if (self::$ins) {
return self::$ins;
}
return self::$ins=new self();
}
/**
* 禁止克隆對(duì)象
*/
public function __clone()
{
throw new curlException('錯(cuò)誤:不能克隆對(duì)象');
}
// 向服務(wù)器發(fā)送最簡(jiǎn)單的get請(qǐng)求
public static function getCurl($url,$header){
// 1.初始化
$ch=curl_init($url); //請(qǐng)求的地址
// 2.設(shè)置選項(xiàng)
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);//獲取的信息以字符串返回,而不是直接輸出(必須)
curl_setopt($ch,CURLOPT_TIMEOUT,10);//超時(shí)時(shí)間(必須)
curl_setopt($ch, CURLOPT_HEADER,0);// 啟用時(shí)會(huì)將頭文件的信息作為數(shù)據(jù)流輸出。
//參數(shù)為1表示輸出信息頭,為0表示不輸出
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); //不驗(yàn)證證書(shū)
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false); //不驗(yàn)證證書(shū)
if(!empty($header)){
curl_setopt($ch,CURLOPT_HTTPHEADER,$header);//設(shè)置頭信息
}
// 3.執(zhí)行
$res=curl_exec($ch);
// 4.關(guān)閉
curl_close($ch);
return $res;
}
}
//curl方法不存在就設(shè)置一個(gè)curl方法
if (!function_exists('mySpClass')) {
function mySpClass() {
return mySpClass::exec();
}
}
?>
以上示例代碼的最終運(yùn)行結(jié)果:第幾章就輸入數(shù)字幾,通過(guò)$_GET['n']傳參
總結(jié):
知識(shí)點(diǎn):curl(tips:curl模塊采集任意網(wǎng)頁(yè)php類(lèi)),正則,解析工具simple_html_dom
雖然寫(xiě)法已經(jīng)初步完善,但是最好能過(guò)部署的自己的服務(wù)器才能有最好的效果,不然只能在電腦觀看,也不見(jiàn)得多方便,可能更愿意忍忍廣告了。
以上就是使用php curl采集頁(yè)面并使用simple_html_dom解析的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
crapy框架的簡(jiǎn)單使用:
網(wǎng)絡(luò)爬蟲(chóng),是在網(wǎng)上進(jìn)行數(shù)據(jù)抓取的程序,使用它能夠抓取特定網(wǎng)頁(yè)的HTML數(shù)據(jù)。雖然我們利用一些庫(kù)開(kāi)發(fā)一個(gè)爬蟲(chóng)程序,但是使用框架可以大大提高效率,縮短開(kāi)發(fā)時(shí)間。Scrapy使用Python編寫(xiě),輕量級(jí)的,簡(jiǎn)單輕巧,并且使用起來(lái)非常的方便。使用Scrapy可以很方便的完成網(wǎng)上數(shù)據(jù)的采集工作,它為我們完成了大量的工作,而不需要自己費(fèi)大力氣去開(kāi)發(fā)。
image
下面我們來(lái)通過(guò)一個(gè)很簡(jiǎn)單的例子來(lái)介紹Scrapy框架的使用
我們要爬的網(wǎng)址是:搜讀網(wǎng): http://www.sodu.cc
我喜歡在這個(gè)網(wǎng)站看小說(shuō),里面的小說(shuō)內(nèi)容還是比較豐富的,推薦讀者喜歡看小說(shuō)的可以來(lái)看看。
因?yàn)橹皇呛?jiǎn)單介紹,所以我只準(zhǔn)備抓取小說(shuō)的標(biāo)題。
好的,基本流程既然確定了,那接下來(lái)就一步一步的完成就可以了。
步驟一: 創(chuàng)建一個(gè)工程和Spider模板
我們先用命令行創(chuàng)建一個(gè)Scrapy工程:
$ scrapy startproject soudu
接著,我們進(jìn)入到工程目錄:
$ cd soudu
我們來(lái)看一下目錄結(jié)構(gòu):
tree# OUT:.├── soudu #外層目錄│ ├── __init__.py #初始化腳本 │ ├── __pycache__ #Python緩存文件。暫時(shí)無(wú)視│ ├── items.py #Items代碼模板,繼承類(lèi)自scrapy.Item│ ├── middlewares.py #Middlewares代碼模板(繼承類(lèi))│ ├── pipelines.py #Pipelines代碼模板(繼承類(lèi))│ ├── settings.py #Scrapy爬蟲(chóng)的配置文件│ └── spiders #Spiders代碼模板目錄 我們寫(xiě)爬蟲(chóng)的地方│ ├── __init__.py│ └── __pycache__└── scrapy.cfg #部署爬蟲(chóng)的配置文件
4 directories, 7 files
最后,我們用命令行創(chuàng)建第一個(gè)Spider:
$ scrapy genspider title www.sodu.cc
這樣我們就創(chuàng)建了一個(gè)名為title的爬蟲(chóng)了。
我們來(lái)看看他長(zhǎng)什么樣,打開(kāi)/spiders/title.py:
# -*- coding: utf-8 -*-import scrapyclass NewsSpider(scrapy.Spider): name='title' allowed_domains=['www.sodu.cc'] start_urls=['http://www.sodu.cc/'] def parse(self, response): pass
可以看到,Scrapy已經(jīng)幫我們把爬蟲(chóng)的框架寫(xiě)好了,我們只要在這個(gè)框架的基礎(chǔ)上進(jìn)行進(jìn)一步的定制就可以了。
步驟二:編寫(xiě)Spider 我們來(lái)著手定制我們的爬蟲(chóng)吧:
看一下詳細(xì)的注釋
# -*- coding: utf-8 -*-import scrapy# 將我們需要爬的項(xiàng)目引入進(jìn)來(lái)from soudu.items import SouduItemclass DemoSpider(scrapy.Spider): #該爬蟲(chóng)的名字 name="title" #規(guī)定爬蟲(chóng)爬取網(wǎng)頁(yè)的域名 allowed_domains=['www.sodu.cc'] #開(kāi)始爬取的url鏈接 start_urls=['http://www.sodu.cc/'] def parse(self, response): ''' parse()函數(shù)接收Response參數(shù),就是網(wǎng)頁(yè)爬取后返回的數(shù)據(jù) 用于處理響應(yīng),他負(fù)責(zé)解析爬取的內(nèi)容 生成解析結(jié)果的字典,并返回新的需要爬取的請(qǐng)求 ''' #由于是demo 我們不做完全的功能, #只要求爬取出第一部小說(shuō)的名字 #xpath規(guī)則可以通過(guò)查看網(wǎng)頁(yè)源文件得出,chrome右鍵檢查定位到所要爬取的內(nèi)容 name=response.xpath('//a[@onclick="getpage(this)"]/text()').extract()[0] #建立一個(gè)items字典,用于保存我們爬到的結(jié)果,并返回給pipline處理 items={} items['第一部小說(shuō)名']=name return items
步驟三:編寫(xiě)Item Pipeline 首先我們編寫(xiě)itmes.py來(lái)定義這個(gè)爬蟲(chóng)框架需要爬哪些內(nèi)容:
# -*- coding: utf-8 -*-# Define here the models for your scraped items## See documentation in:# https://doc.scrapy.org/en/latest/topics/items.htmlimport scrapyclass SouduItem(scrapy.Item): # define the fields for your item here like: # name=scrapy.Field() name=scrapy.Field()
接著我們編寫(xiě) piplines.py來(lái)處理spider爬到的內(nèi)容:
# -*- coding: utf-8 -*-# Define your item pipelines here## Don't forget to add your pipeline to the ITEM_PIPELINES setting# See: http://doc.scrapy.org/en/latest/topics/item-pipeline.htmlclass ZimukuPipeline(object): def process_item(self, item, spider): # 因?yàn)槭亲詈?jiǎn)單的,所以我們把爬到的結(jié)果打印一下 print(item) return item
步驟四:優(yōu)化配置Settings.py
# -*- coding: utf-8 -*-# Scrapy settings for soudu project## For simplicity, this file contains only settings considered important or# commonly used. You can find more settings consulting the documentation:## https://doc.scrapy.org/en/latest/topics/settings.html# https://doc.scrapy.org/en/latest/topics/downloader-middleware.html# https://doc.scrapy.org/en/latest/topics/spider-middleware.htmlBOT_NAME='soudu'SPIDER_MODULES=['soudu.spiders']NEWSPIDER_MODULE='soudu.spiders'# Crawl responsibly by identifying yourself (and your website) on the user-agent#USER_AGENT='soudu (+http://www.yourdomain.com)'# Obey robots.txt rulesROBOTSTXT_OBEY=True#只增加了這一行,通過(guò)配置告訴Scrapy明白是誰(shuí)來(lái)處理結(jié)果ITEM_PIPELINES={ 'soudu.pipelines.SouduPipeline': 300,}
好了,這樣一個(gè)爬蟲(chóng)就算完成了,那怎么獲取爬到的結(jié)果呢???
首先我們通過(guò)命令來(lái)執(zhí)行爬蟲(chóng):
$ scrapy crawl title
讓我們這個(gè)最最簡(jiǎn)單的爬蟲(chóng)跑起來(lái)。
來(lái)看一下結(jié)果:
我只截取部分我們需要的內(nèi)容,其他的我且暫不寫(xiě)出了:
2018-08-03 19:31:53 [scrapy.core.scraper] DEBUG: Scraped from <200 http://www.sodu.cc/>{'第一部小說(shuō)名': '圣墟'}
是不是可以看到我們需要找到的內(nèi)容了????
Scrapy框架的基本使用已經(jīng)說(shuō)完了,以后我會(huì)一步一步來(lái)講解其他的例子!
本文就分享到這里,更多python學(xué)習(xí)可以關(guān)注我們哦!
注:python學(xué)習(xí)關(guān)注我們企鵝qun: 8393 83765 各類(lèi)入門(mén)學(xué)習(xí)資料免費(fèi)分享哦!
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。