명령 행 :
scrapy shell https://news.cnblogs.com/
디버깅, URL의 모든 기사 페이지를 얻을 :
>>> articles_link_xpath = '//*[@class="news_entry"]/a/@href'
>>> articles_link_selector = response.xpath(articles_link_xpath)
>>> articles_link_selector
[<Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630083/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630082/'>, <Selector xpath=
'//*[@class="news_entry"]/a/@href' data='/n/630081/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630080/'>, <Selector xpath='//*[@class="news
_entry"]/a/@href' data='/n/630079/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630078/'>, <Selector xpath='//*[@class="news_entry"]/a/@href'
data='/n/630077/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630076/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630075/
'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630074/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630073/'>, <Selector xpa
th='//*[@class="news_entry"]/a/@href' data='/n/630072/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630071/'>, <Selector xpath='//*[@class="n
ews_entry"]/a/@href' data='/n/630070/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630069/'>, <Selector xpath='//*[@class="news_entry"]/a/@hr
ef' data='/n/630068/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630067/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/6300
66/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630065/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630064/'>, <Selector
xpath='//*[@class="news_entry"]/a/@href' data='/n/630063/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630061/'>, <Selector xpath='//*[@class
="news_entry"]/a/@href' data='/n/630062/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630060/'>, <Selector xpath='//*[@class="news_entry"]/a/
@href' data='/n/630059/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630058/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/6
30057/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630056/'>, <Selector xpath='//*[@class="news_entry"]/a/@href' data='/n/630055/'>, <Select
or xpath='//*[@class="news_entry"]/a/@href' data='/n/630054/'>]
>>> articles_link_list = articles_link_selector.extract()
>>> articles_link_list
['/n/630083/', '/n/630082/', '/n/630081/', '/n/630080/', '/n/630079/', '/n/630078/', '/n/630077/', '/n/630076/', '/n/630075/', '/n/630074/', '/n/630073/', '/n/
630072/', '/n/630071/', '/n/630070/', '/n/630069/', '/n/630068/', '/n/630067/', '/n/630066/', '/n/630065/', '/n/630064/', '/n/630063/', '/n/630061/', '/n/63006
2/', '/n/630060/', '/n/630059/', '/n/630058/', '/n/630057/', '/n/630056/', '/n/630055/', '/n/630054/']
>>> articles_link = ['https://news.cnblogs.com' + url for url in articles_link_list]
>>> articles_link
['https://news.cnblogs.com/n/630083/', 'https://news.cnblogs.com/n/630082/', 'https://news.cnblogs.com/n/630081/', 'https://news.cnblogs.com/n/630080/', 'https
://news.cnblogs.com/n/630079/', 'https://news.cnblogs.com/n/630078/', 'https://news.cnblogs.com/n/630077/', 'https://news.cnblogs.com/n/630076/', 'https://news
.cnblogs.com/n/630075/', 'https://news.cnblogs.com/n/630074/', 'https://news.cnblogs.com/n/630073/', 'https://news.cnblogs.com/n/630072/', 'https://news.cnblog
s.com/n/630071/', 'https://news.cnblogs.com/n/630070/', 'https://news.cnblogs.com/n/630069/', 'https://news.cnblogs.com/n/630068/', 'https://news.cnblogs.com/n
/630067/', 'https://news.cnblogs.com/n/630066/', 'https://news.cnblogs.com/n/630065/', 'https://news.cnblogs.com/n/630064/', 'https://news.cnblogs.com/n/630063
/', 'https://news.cnblogs.com/n/630061/', 'https://news.cnblogs.com/n/630062/', 'https://news.cnblogs.com/n/630060/', 'https://news.cnblogs.com/n/630059/', 'ht
tps://news.cnblogs.com/n/630058/', 'https://news.cnblogs.com/n/630057/', 'https://news.cnblogs.com/n/630056/', 'https://news.cnblogs.com/n/630055/', 'https://n
ews.cnblogs.com/n/630054/']
위의 코드에 의해, 우리는 필터 뒤에 문자열이 XPath를 적용 것을 볼 수있다 :
/@href
당신은 태그 내에 HREF 특성을 얻을 수 있습니다.
start_urls를로 복원
https://news.cnblogs.com/
위의 디버깅 모자이크를 달성하기 위해 URL 유형의 목록을 생성하는 데 사용됩니다 만, 제공 URLLIB 우리는 방법으로 완료됩니다.
다운로드에 문서 목록 페이지 문서 URL, scrapy을 획득 한 후, 구문 분석 특정 필드 : 코드 구현 구문 분석 기능, 즉 다음 첫 번째 함수.
from scrapy.http import Request
from urllib import parse
읽기 기능을 구문 분석 :
def parse(self, response):
"""
1. 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
2. 获取下一页的url,交给scrapy进行下载,下载完成后交给parse
"""
# 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
articles_link = response.xpath('//*[@class="news_entry"]/a/@href').extract()
for url in articles_link:
yield Request(url=parse.urljoin(response.url, url), callback=self.parse_detail)
pass
상기 코드는 먼저 더 융통성 urljoin 완전한 URL을 urljoin 의해 얻어진 for 루프에서, 스 플라이 싱 전에 XPath에 의해 URL을 파싱, URL 및 상기 요구에 파라미터로서 전달 된 콜백 함수하고 명령 수율 , 당신은 다운로드를 달성하고 콜백을 구문 분석 할 수 있습니다.
(다시 가져올 파일의 시작 부분에) 클래스 parse_detail 과정에서 캡슐화 된 특정 필드를 분석하기 전에 :
def parse_detail(self, response):
"""
解析文章具体字段
"""
# 标题
title = response.xpath('//*[@id="news_title"]/a/text()').extract_first("Untitled")
# 发布日期
create_date = re.findall('\d{4}-\d{2}-\d{2}', response.xpath('//*[@id="news_info"]/span[2]/text()').extract_first("0000-00-00"))[0]
# 正文
content = response.xpath('//*[@id="news_body"]').extract_first("No content")
# 标签
tags = ','.join(response.xpath('//*[@id="news_more_info"]/div/a/text()').extract())
# 来源
source = response.xpath('//*[@id="link_source2"]/text()').extract_first('Unknown')
pass
다음과 같은 기능 즉, 두 번째 기능의 개발을 구문 분석 : 다운로드 scrapy를 다음 페이지의 URL을 가져, 다운로드가 구문 분석이 완료됩니다.
첫 번째는 쉘 디버그 scrapy입니다 :
>>> next_url_xpath = '//div[@class="pager"]/a[last()]/@href'
>>> next_url_selector = response.xpath(next_url_xpath)
>>> next_url_selector
[<Selector xpath='//div[@class="pager"]/a[last()]/@href' data='/n/page/2/'>]
>>> next_url = next_url_selector.extract_first()
>>> next_url
'/n/page/2/'
구문 분석 기능은 다음과 같은 논리를 추가합니다 :
# 获取下一页的url,交给scrapy进行下载,下载完成后交给parse
next_url = response.xpath('//div[@class="pager"]/a[not(@class)]/@href').extract_first('end')
if next_url != 'end':
next_url = parse.urljoin(response.url, next_url)
yield Request(url=next_url, callback=self.parse)
pass
위의 마지막 페이지로 주어진다는 다음 라벨 따라서 더 이상 마지막 ()를 사용, 더 이상 없다 획득하지 않지만 클래스 속성 태그를 선택하지 않는, 방법은 다음과 같습니다
/a[not(@class)]
전반적으로, 대한 cnblogs.py :
# -*- coding: utf-8 -*-
import scrapy
import re
from scrapy.http import Request
from urllib import parse
class CnblogsSpider(scrapy.Spider):
name = 'cnblogs'
allowed_domains = ['news.cnblogs.com'] # 允许的域名
start_urls = ['https://news.cnblogs.com'] # 起始url
def parse(self, response):
"""
1. 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
2. 获取下一页的url,交给scrapy进行下载,下载完成后交给parse
"""
# 获取文章列表页中的文章的url,交给scrapy下载后,进行具体字段的解析
articles_link = response.xpath('//*[@class="news_entry"]/a/@href').extract()
for url in articles_link:
yield Request(url=parse.urljoin(response.url, url), callback=self.parse_detail)
pass
# 获取下一页的url,交给scrapy进行下载,下载完成后交给parse
next_url = response.xpath('//div[@class="pager"]/a[not(@class)]/@href').extract_first('end')
if next_url != 'end':
next_url = parse.urljoin(response.url, next_url)
yield Request(url=next_url, callback=self.parse)
pass
def parse_detail(self, response):
"""
解析文章具体字段
"""
# 标题
title = response.xpath('//*[@id="news_title"]/a/text()').extract_first("Untitled")
# 发布日期
create_date = re.findall('\d{4}-\d{2}-\d{2}', response.xpath('//*[@id="news_info"]/span[2]/text()').extract_first("0000-00-00"))[0]
# 正文
content = response.xpath('//*[@id="news_body"]').extract_first("No content")
# 标签
tags = ','.join(response.xpath('//*[@id="news_more_info"]/div/a/text()').extract())
# 来源
source = response.xpath('//*[@id="link_source2"]/text()').extract_first('Unknown')
pass
우리가 scrapy을 사용하기 때문에, 작업 중 일부는 우리가 사용 URLLIB 또는 제작 요청하지 않아도, 그 주목해야한다. 우리가 콜백 메커니즘을 사용하는 것이 요청은 실제로 비동기입니다. 비동기 성능은 내용이 엄격한 순서의 같은 페이지가 아닌 들어오는 요청 URL의 순서에 따라되지 않습니다에 우리가 얻을 수 있다는 것입니다. 또한, 다른 페이지는 첫 번째의 첫 페이지의 내용의 대부분은 얻을 수있는 페이지의 뒤에서 앞 페이지가 나타납니다의 작은 부분을 얻을 수 있습니다.
파충류를 종료 할 때? 사실, 콜백은 재귀, 또는주기의 일종으로 볼 수있다. 당신은 사이클로 볼 때 종료 문제는 생각하기 어려운 더 이상 없을 때.
또한, 우리의 사이트 크롤링 및보기로 로그인이 필요하지 않습니다 거의 3 일간의 문서를 발견, 3 일 기사 전에이 장 우리의 그들은 우리가이 문제를 해결할 다음 장을 참조하기 전에 로그인 할 필요가있다한다 전용 콘텐츠의 거의 3 일 크롤링. 그래서, 다음 parse_detail를 다시 작성 :
def parse_detail(self, response):
"""
解析文章具体字段
"""
if 'account' in response.url:
pass
else:
# 标题
title = response.xpath('//*[@id="news_title"]/a/text()').extract_first("Untitled")
# 发布日期
create_date = re.findall('\d{4}-\d{2}-\d{2}', response.xpath('//*[@id="news_info"]/span[2]/text()').extract_first("0000-00-00"))[0]
# 正文
content = response.xpath('//*[@id="news_body"]').extract_first("No content")
# 标签
tags = ','.join(response.xpath('//*[@id="news_more_info"]/div/a/text()').extract())
# 来源
source = response.xpath('//*[@id="link_source2"]/text()').extract_first('Unknown')
pass
pass