1.伯樂在線
網站頁面如下圖所示:
1.1 新建爬蟲工程
命令:scrapy startproject BoleArticle
新建爬蟲工程命令
命令:scrapy genspider article "blog.jobbole.com" 注意:運行此命令時必須在爬蟲工程文件夾內,如下圖路徑所示。
新建爬蟲文件命令
6個字段:title、publishTime、category、digest、detailUrl、img_url,數據類型為scrapy.Field對象
<code>import scrapyfrom scrapy import Fieldclass BolearticleItem(scrapy.Item): title = Field() publishTime = Field() category = Field() digest = Field() detailUrl = Field() img_url =Field()/<code>
1.3 編輯article.py文件
parse函數用於解析最大共有多少頁,並將每一個目錄頁面的鏈接通過字符串拼接的方法傳給下一級解析函數 scrapy.Request 函數里面有2個參數:
第1個參數數據類型是字符串,是下一級解析頁面的url鏈接;
第2個參數數據類型是函數對象,是ArticleSpider裡面函數的函數名。
parse1函數用於解析每一個目錄頁面的文章信息
共有6個字段:title、publishTime、category、digest、detailUrl、img_url,publishTime字段是通過正則表達式找到的,
具體是使用re.search方法。其他字段通過xpath可以找到。
<code>import scrapyfrom ..items import BolearticleItemimport reclass ArticleSpider(scrapy.Spider): name = 'article' allowed_domains = ['blog.jobbole.com'] start_urls = ['http://blog.jobbole.com/all-posts/'] def parse(self, response): pageNum = response.xpath("//a[@class='page-numbers']/text()")[-1].extract() for i in range(1,int(pageNum)+1): url = "http://blog.jobbole.com/all-posts/page/{}/".format(i) yield scrapy.Request(url,callback=self.parse1) def parse1(self,response): def find(xpath, pNode=response): if len(pNode.xpath(xpath)): return pNode.xpath(xpath).extract()[0] else: return '' article_list = response.xpath("//div[@class='post floated-thumb']") for article in article_list: item = BolearticleItem() item['title'] = find("div[1]/a/@title",article) pTagStr = find("div[2]/p",article) item['publishTime'] = re.search("\\d+/\\d+/\\d+",pTagStr).group(0) item['category'] = find("div[2]/p/a[2]/text()",article) item['digest'] = find("div[2]/span/p/text()",article) item['detailUrl'] = find("div[2]/p/a[1]/@href",article) item['img_url'] = find("div[1]/a/img/@src",article) yield item/<code>
1.4 編輯pipelines.py文件
在管道類初始化時,刪除並新建表article1 下面一段代碼中有2處需要修改:
1.數據庫名,第4行的變量database;
2.數據庫連接的密碼,第8行的變量passwd 代碼第28行變量insert_sql的數據類型是字符串,通過字符串拼接形成插入數據的sql語句。
理解變量fieldStr、valueStr形成過程的難點是字符串的join方法和推導式 每次插入數據後都執行self.conn.commit()
<code>import pymysqlfrom time import timedef getConn(database ="bolearticle"): args = dict( host = 'localhost', user = 'root', passwd = '... your password', charset = 'utf8', db = database ) return pymysql.connect(**args)class BolearticlePipeline(object): startTime = time() conn = getConn() cursor = conn.cursor() drop_sql = "drop table if exists article1" cursor.execute(drop_sql) create_sql = "create table article1(title varchar(200) primary key,publishtime varchar(30)," \\ "category varchar(30),digest varchar(500)," \\ "detailUrl varchar(200),img_url varchar(200));" cursor.execute(create_sql) def process_item(self, item, spider): fieldStr = ','.join(['`%s`'%k for k in item.keys()]) valuesStr = ','.join(['"%s"'%v for v in item.values()]) insert_sql = "insert into article1(%s) values(%s)" %(fieldStr,valuesStr) self.cursor.execute(insert_sql) self.conn.commit() return item/<code>
1.5 編輯settings.py文件
關鍵點是最後3行要開啟管道,CONCURRENT_REQUESTS變量設置為96能夠較好利用多線程性能 ROBOTSTXT_OBEY設置為False,意思是不遵守爬蟲協議,也稱機器人協議。
如果設置為True,即遵守爬蟲協議,則可能訪問受限。
<code>BOT_NAME = 'BoleArticle'SPIDER_MODULES = ['BoleArticle.spiders']NEWSPIDER_MODULE = 'BoleArticle.spiders'ROBOTSTXT_OBEY = FalseCONCURRENT_REQUESTS = 96ITEM_PIPELINES = { 'BoleArticle.pipelines.BolearticlePipeline': 300,}/<code>
1.6 運行結果
在命令行中運行命令:scrapy crawl article 查看數據庫,結果截圖如下:
2.網易新聞圖片
用urllib.parse.unquote方法查看%E4%B8%AD%E5%9B%BD的中文對應字符,如下圖所示:
網站頁面如下圖所示,需要爬取2400張圖片:
2.1 新建爬蟲工程
新建爬蟲工程命令:scrapy startproject NeteasyImage 進入爬蟲工程文件夾:cd .\\NeteasyImage 新建爬蟲文件命令:scrapy genspider image "news.163.com"
3個字段:id、img_url、img_title
<code>import scrapyfrom scrapy import Fieldclass NeteasyimageItem(scrapy.Item): id = Field() img_url = Field() img_title = Field()/<code>
image_number變量是下載圖片的數量。
start_urls變量數據類型為列表,其中的每個元素的數據類型為字符串,是獲取圖片鏈接的請求url。 start_urls中的元素髮出請求返回的內容為json類型的文本。
json.loads方法中有1個參數,參數數據類型為字符串,這個方法的作用可以把字符串轉為字典,要求字符串必須以{開頭,以}結束。
對於下圖的json文本來說,需要刪除左邊的var jsonres=,刪除最後一個字符; 轉化後的字典賦值給jsonLoad變量,jsonLoad['hits']數據類型為列表,當中有圖片的鏈接,標題等。
id字段用來判斷是第幾張圖。
<code>import scrapyimport jsonfrom ..items import NeteasyimageItemclass ImageSpider(scrapy.Spider): name = 'image' allowed_domains = ['netease.com'] image_number = 2000 urlBefore = "http://uvs.youdao.com/search?site=photogalaxy.163.com" \\ "&sort=time&channelid=&q=%E4%B8%AD%E5%9B%BD&length=100&start={}" start_urls = [] for i in range(0, image_number, 100): start_urls.append(urlBefore.format(i)) count = 0 def parse(self, response): jsonStr = response.text.lstrip("var jsonres=").strip().strip(";") jsonLoad = json.loads(jsonStr) for image in jsonLoad['hits']: self.count += 1 item = NeteasyimageItem() item['id'] = self.count item['img_title'] = image['setname'] item['img_url'] = image['imgsrc'] yield item/<code>
2.4 編輯settings.py文件
關鍵點是最後3行要開啟管道,CONCURRENT_REQUESTS變量設置為96能夠較好利用多線程性能 ROBOTSTXT_OBEY設置為False,意思是不遵守爬蟲協議,也稱機器人協議。
如果設置為True,即遵守爬蟲協議,則可能訪問受限。
<code>import osBOT_NAME = 'NeteasyImage'SPIDER_MODULES = ['NeteasyImage.spiders']NEWSPIDER_MODULE = 'NeteasyImage.spiders'ROBOTSTXT_OBEY = FalseCONCURRENT_REQUESTS = 96CONCURRENT_ITEMS = 200IMAGES_STORE = os.getcwd() + '/images/'ITEM_PIPELINES = { 'NeteasyImage.pipelines.NeteasyimagePipeline': 300,}/<code>
2.5 編輯pipelines.py文件
<code>下面代碼比較難懂的地方是item_completed函數中的results參數results數據類型為列表,列表中的第一個元素為元組,元組中第一個元素result[0][0]數據類型為布爾,是下載結果是否成功。result[0][1]是下載圖片返回的一些信息,數據類型為字典,其中有3個鍵值對,3個鍵為url、path、checksum。格式如下所示。{'url': 'http://img2.cache.netease.com/photo/0003/2016-07-18/t_BS95B1C900AJ0003.jpg', 'path':'full/98979c89e2b5e6ef9926183dab4e8bf5a8efa8a4.jpg', 'checksum': '15d5231fcd77d81ddd58d7db6a07c1ce'}url是下載圖片的鏈接,path是下載圖片保存的路徑,checksum是下載圖片的文件校驗和。用os.rename方法重命名圖片文件。/<code>
<code>from scrapy.pipelines.images import ImagesPipelineimport scrapyfrom .settings import IMAGES_STORE as images_storeimport osclass NeteasyimagePipeline(ImagesPipeline): def get_media_requests(self, item, info): yield scrapy.Request(item['img_url']) def item_completed(self, results, item, info): if results[0][0]: old_path = images_store + results[0][1]['path'] fileName = "{}-{}.jpg".format(item['id'],item['img_title']) new_path = images_store + fileName os.rename(old_path,new_path)/<code>
2.6 運行結果
在命令行中運行命令:scrapy crawl image 查看圖片保存的文件夾,如下圖所示:
最後小編幫助大家整理了一套python教程,下面展示了部分,希望也能幫助對編程感興趣,想做數據分析,人工智能、爬蟲或者希望從事編程開發的小夥伴,畢竟python工資也還可以,如果能幫到你請點贊、點贊、點贊。
PS:如果你喜歡python,並覺得這篇文章對你有益的話,麻煩多多點贊關注支持!
閱讀更多 程序猿老旭 的文章