Scrapy爬取釜山行政区数据时缺失无链接记录求助
Scrapy爬取表格遗漏无链接记录的问题解决
问题场景
爬取目标网站的行政区表格数据时,发现带跳转链接的记录能正常抓取,但像Busan这种<td class="sc">标签内无链接的行会被遗漏。
有链接的行HTML示例:
<tbody class="admin1"> <tr class="rname" itemscope="" itemtype="http://schema.org/AdministrativeArea" onclick="javascript:sym('21080')"><td class="rname" id="i21080" data-wiki="Buk District, Busan" data-wd="Q50394" data-area="39.726" data-density="7052.7362"><a href="javascript:sym('21080')"><span itemprop="name">Buk-gu</span></a> [<span itemprop="name">North Distrikt</span>]</td><td class="rstatus">City District</td><td class="rnative"><span itemprop="name">북구</span></td><td class="rpop prio4">329,336</td><td class="rpop prio3">302,141</td><td class="rpop prio2">299,182</td><td class="rpop prio1">280,177</td><td class="sc"><a itemprop="url" href="/en/southkorea/busan/admin/21080__buk_gu/">→</a></td></tr> </tbody>
无链接的行HTML示例:
<tbody class="admin0"> <tr><td class="rname">Busan</td><td class="rstatus">Metropolitan City</td><td class="rnative"><span itemprop="name">부산광역시</span></td><td class="rpop prio4">3,523,582</td><td class="rpop prio3">3,414,950</td><td class="rpop prio2">3,448,737</td><td class="rpop prio1">3,349,016</td><td class="sc"></td></tr> </tbody>
当前使用代码
from gc import callbacks import scrapy class WebsiteItem(scrapy.Item): item_name = scrapy.Field() item_status = scrapy.Field() class WebsiteSpider(scrapy.spiders.CrawlSpider): name = "posts" start_urls = ["https://www.citypopulation.de/en/southkorea/"] rules = ( scrapy.spiders.Rule(scrapy.linkextractors.LinkExtractor(restrict_css="div#prov_div > ul > li > a"), follow=True), scrapy.spiders.Rule(scrapy.linkextractors.LinkExtractor(restrict_css="table#tl > tbody > tr > td"), callback="parse") ) def parse(self, response): website_item = WebsiteItem() website_item['item_name'] = response.css("td.rname span::text").get() website_item['item_status'] = response.css("td.rstatus::text").get() return website_item
问题根源
当前的rules里,第二个规则用LinkExtractor匹配表格行里的链接,只有当行内存在可提取的链接时,才会触发parse方法抓取子页面数据。无链接的行不会被LinkExtractor识别,自然不会被处理。另外,parse方法仅处理子页面,没有直接从列表页提取无链接行的数据。
解决方案
调整规则和解析逻辑:
- 新增规则直接处理包含目标表格的列表页,遍历所有表格行提取数据(无论是否有链接)
- 保留原有子页面爬取规则,单独用解析方法处理子页面数据,避免冲突
修改后的完整代码
import scrapy from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor class WebsiteItem(scrapy.Item): item_name = scrapy.Field() item_status = scrapy.Field() native_name = scrapy.Field() # 可选:新增本地名字段 population_latest = scrapy.Field() # 可选:新增最新人口字段 class WebsiteSpider(CrawlSpider): name = "posts" start_urls = ["https://www.citypopulation.de/en/southkorea/"] rules = ( # 跟进省级列表链接,进入各城市行政区页面 Rule(LinkExtractor(restrict_css="div#prov_div > ul > li > a"), follow=True), # 处理带链接的行政区详情页 Rule(LinkExtractor(restrict_css="table#tl td.sc > a"), callback="parse_detail"), # 处理列表页,提取所有表格行数据(含无链接行) Rule(LinkExtractor(restrict_css="div#prov_div > ul > li > a"), callback="parse_list", follow=True), ) def parse_list(self, response): # 遍历列表页所有表格行 for row in response.css("table#tl tbody tr"): item = WebsiteItem() # 提取名称:优先取span,无span则直接取td文本(如Busan) item['item_name'] = row.css("td.rname span::text").get() or row.css("td.rname::text").get().strip() item['item_status'] = row.css("td.rstatus::text").get().strip() item['native_name'] = row.css("td.rnative span::text").get().strip() item['population_latest'] = row.css("td.rpop.prio4::text").get().strip() yield item def parse_detail(self, response): # 处理子页面详情数据,可按需扩展字段 item = WebsiteItem() item['item_name'] = response.css("td.rname span::text").get() item['item_status'] = response.css("td.rstatus::text").get() # 可继续提取子页面其他数据 yield item
说明
parse_list方法专门处理列表页,遍历所有表格行,解决无链接行遗漏问题parse_detail方法处理带链接的子页面,保留原有子页面数据抓取能力- 新增的可选字段可根据实际需求调整或删除
内容的提问来源于stack exchange,提问作者Coastie
相关产品推荐
相关产品推荐

